Merge from trunk
[emacs.git] / src / widget.c
blob2301f76c7c9c397c6c019df81b31f5872da7aaa5
1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* Emacs 19 face widget ported by Fred Pierresteguy */
22 /* This file has been censored by the Communications Decency Act.
23 That law was passed under the guise of a ban on pornography, but
24 it bans far more than that. This file did not contain pornography,
25 but it was censored nonetheless.
27 For information on US government censorship of the Internet, and
28 what you can do to bring back freedom of the press, see the web
29 site http://www.vtw.org/
32 #include <config.h>
33 #include <stdio.h>
34 #include <setjmp.h>
35 #include "lisp.h"
36 #include "xterm.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "window.h"
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"
54 #include <signal.h>
55 #include "syssignal.h"
57 #include "character.h"
58 #include "font.h"
60 /* This sucks: this is the first default that x-faces.el tries. This won't
61 be used unless neither the "Emacs.EmacsFrame" resource nor the
62 "Emacs.EmacsFrame" resource is set; the frame
63 may have the wrong default size if this font doesn't exist, but some other
64 font that x-faces.el does. The workaround is to specify some font in the
65 resource database; I don't know a solution other than duplicating the font-
66 searching code from x-faces.el in this file.
68 This also means that if "Emacs.EmacsFrame" is specified as a non-
69 existent font, then Xt is going to substitute "XtDefaultFont" for it,
70 which is a different size than this one. The solution for this is to
71 make x-faces.el try to use XtDefaultFont. The problem with that is that
72 XtDefaultFont is almost certainly variable-width.
74 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
76 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
79 static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
80 static void EmacsFrameDestroy (Widget widget);
81 static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
82 void EmacsFrameResize (Widget widget);
83 static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
84 static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
87 #undef XtOffset
88 #define XtOffset(p_type,field) \
89 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
90 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
92 static XtResource resources[] = {
93 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
94 offset (geometry), XtRString, (XtPointer) 0},
95 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
96 offset (iconic), XtRImmediate, (XtPointer) False},
98 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
99 offset (frame), XtRImmediate, 0},
101 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
102 offset (minibuffer), XtRImmediate, (XtPointer)0},
103 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
104 offset (unsplittable), XtRImmediate, (XtPointer)0},
105 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
106 offset (internal_border_width), XtRImmediate, (XtPointer)4},
107 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
108 offset (interline), XtRImmediate, (XtPointer)0},
109 {XtNfont, XtCFont, XtRFontStruct, sizeof(struct font *),
110 offset(font),XtRString, DEFAULT_FACE_FONT},
111 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
112 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
113 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
114 offset(cursor_color), XtRString, "XtDefaultForeground"},
115 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
116 offset (bar_cursor), XtRImmediate, (XtPointer)0},
117 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
118 offset (visual_bell), XtRImmediate, (XtPointer)0},
119 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
120 offset (bell_volume), XtRImmediate, (XtPointer)0},
123 #undef offset
126 static XtActionsRec
127 emacsFrameActionsTable [] = {
128 {"keypress", key_press},
129 {"focus_in", emacs_frame_focus_handler},
130 {"focus_out", emacs_frame_focus_handler},
133 static char
134 emacsFrameTranslations [] = "\
135 <KeyPress>: keypress()\n\
136 <FocusIn>: focus_in()\n\
137 <FocusOut>: focus_out()\n\
141 EmacsFrameClassRec emacsFrameClassRec = {
142 { /* core fields */
143 /* superclass */ &widgetClassRec,
144 /* class_name */ "EmacsFrame",
145 /* widget_size */ sizeof(EmacsFrameRec),
146 /* class_initialize */ 0,
147 /* class_part_initialize */ 0,
148 /* class_inited */ FALSE,
149 /* initialize */ EmacsFrameInitialize,
150 /* initialize_hook */ 0,
151 /* realize */ EmacsFrameRealize,
152 /* actions */ 0, /*emacsFrameActionsTable*/
153 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
154 /* resources */ resources,
155 /* resource_count */ XtNumber(resources),
156 /* xrm_class */ NULLQUARK,
157 /* compress_motion */ TRUE,
158 /* compress_exposure */ TRUE,
159 /* compress_enterleave */ TRUE,
160 /* visible_interest */ FALSE,
161 /* destroy */ EmacsFrameDestroy,
162 /* resize */ EmacsFrameResize,
163 /* expose */ XtInheritExpose,
164 /* set_values */ EmacsFrameSetValues,
165 /* set_values_hook */ 0,
166 /* set_values_almost */ XtInheritSetValuesAlmost,
167 /* get_values_hook */ 0,
168 /* accept_focus */ XtInheritAcceptFocus,
169 /* version */ XtVersion,
170 /* callback_private */ 0,
171 /* tm_table */ 0, /*emacsFrameTranslations*/
172 /* query_geometry */ EmacsFrameQueryGeometry,
173 /* display_accelerator */ XtInheritDisplayAccelerator,
174 /* extension */ 0
178 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
180 static void
181 get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
183 struct frame* f = ew->emacs_frame.frame;
184 *pixel_width = FRAME_COLUMN_WIDTH (f);
185 *pixel_height = FRAME_LINE_HEIGHT (f);
188 static void
189 pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
191 struct frame* f = ew->emacs_frame.frame;
192 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
193 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
196 static void
197 char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
199 struct frame* f = ew->emacs_frame.frame;
200 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
201 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
204 static void
205 round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
207 int char_width;
208 int char_height;
209 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
210 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
213 static Widget
214 get_wm_shell (Widget w)
216 Widget wmshell;
218 for (wmshell = XtParent (w);
219 wmshell && !XtIsWMShell (wmshell);
220 wmshell = XtParent (wmshell));
222 return wmshell;
225 #if 0 /* Currently not used. */
227 static void
228 mark_shell_size_user_specified (wmshell)
229 Widget wmshell;
231 if (! XtIsWMShell (wmshell)) abort ();
232 /* This is kind of sleazy, but I can't see how else to tell it to make it
233 mark the WM_SIZE_HINTS size as user specified when appropriate. */
234 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
237 #endif
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 #if 0
247 static Boolean first_frame_p = True;
248 #endif
250 static void
251 set_frame_size (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 /* Hairily merged geometry */
289 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
290 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
292 Widget wmshell = get_wm_shell ((Widget) ew);
293 /* Each Emacs shell is now independent and top-level. */
295 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
297 /* We don't need this for the moment. The geometry is computed in
298 xfns.c. */
299 #if 0
300 /* If the EmacsFrame doesn't have a geometry but the shell does,
301 treat that as the geometry of the frame. (Is this bogus?
302 I'm not sure.) */
303 if (ew->emacs_frame.geometry == 0)
304 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
306 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
307 this bogus? I'm not sure.) */
308 if (!ew->emacs_frame.iconic)
309 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
313 char *geom = 0;
314 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
315 if (geom)
316 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
319 if (ew->emacs_frame.geometry)
320 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
321 &frame_x, &frame_y,
322 &frame_w, &frame_h);
324 if (first_frame_p)
326 /* If this is the first frame created:
327 ====================================
329 - Use the ApplicationShell's size/position, if specified.
330 (This is "Emacs.geometry", or the "-geometry" command line arg.)
331 - Else use the EmacsFrame's size/position.
332 (This is "*Frame-NAME.geometry")
334 - If the AppShell is iconic, the frame should be iconic.
336 AppShell comes first so that -geometry always applies to the first
337 frame created, even if there is an "every frame" entry in the
338 resource database.
340 if (app_flags & (XValue | YValue))
342 x = app_x; y = app_y;
343 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
345 else if (frame_flags & (XValue | YValue))
347 x = frame_x; y = frame_y;
348 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
351 if (app_flags & (WidthValue | HeightValue))
353 w = app_w; h = app_h;
354 flags |= (app_flags & (WidthValue | HeightValue));
356 else if (frame_flags & (WidthValue | HeightValue))
358 w = frame_w; h = frame_h;
359 flags |= (frame_flags & (WidthValue | HeightValue));
362 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
363 if (!ew->emacs_frame.iconic)
364 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
366 first_frame_p = False;
368 else
370 /* If this is not the first frame created:
371 ========================================
373 - use the EmacsFrame's size/position if specified
374 - Otherwise, use the ApplicationShell's size, but not position.
376 So that means that one can specify the position of the first frame
377 with "Emacs.geometry" or `-geometry'; but can only specify the
378 position of subsequent frames with "*Frame-NAME.geometry".
380 AppShell comes second so that -geometry does not apply to subsequent
381 frames when there is an "every frame" entry in the resource db,
382 but does apply to the first frame.
384 if (frame_flags & (XValue | YValue))
386 x = frame_x; y = frame_y;
387 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
390 if (frame_flags & (WidthValue | HeightValue))
392 w = frame_w; h = frame_h;
393 flags |= (frame_flags & (WidthValue | HeightValue));
395 else if (app_flags & (WidthValue | HeightValue))
397 w = app_w;
398 h = app_h;
399 flags |= (app_flags & (WidthValue | HeightValue));
402 #endif /* 0 */
404 struct frame *f = ew->emacs_frame.frame;
405 Dimension pixel_width, pixel_height;
407 /* Take into account the size of the scrollbar. Always use the
408 number of columns occupied by the scroll bar here otherwise we
409 might end up with a frame width that is not a multiple of the
410 frame's character width which is bad for vertically split
411 windows. */
412 f->scroll_bar_actual_width
413 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
415 compute_fringe_widths (f, 0);
417 #if 0 /* This can run Lisp code, and it is dangerous to give
418 out the frame to Lisp code before it officially exists.
419 This is handled in Fx_create_frame so not needed here. */
420 change_frame_size (f, h, w, 1, 0, 0);
421 #endif
422 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
423 ew->core.width = pixel_width;
424 ew->core.height = pixel_height;
426 #if 0 /* xfns.c takes care of this now. */
427 /* If a position was specified, assign it to the shell widget.
428 (Else WM won't do anything with it.)
430 if (flags & (XValue | YValue))
432 /* the tricky things with the sign is to make sure that
433 -0 is printed -0. */
434 int len;
435 char *tem;
436 sprintf (shell_position, "=%c%d%c%d",
437 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
438 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
439 len = strlen (shell_position) + 1;
440 tem = (char *) xmalloc (len);
441 strncpy (tem, shell_position, len);
442 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
444 else if (flags & (WidthValue | HeightValue))
446 int len;
447 char *tem;
448 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
449 len = strlen (shell_position) + 1;
450 tem = (char *) xmalloc (len);
451 strncpy (tem, shell_position, len);
452 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
455 /* If the geometry spec we're using has W/H components, mark the size
456 in the WM_SIZE_HINTS as user specified. */
457 if (flags & (WidthValue | HeightValue))
458 mark_shell_size_user_specified (wmshell);
460 /* Also assign the iconic status of the frame to the Shell, so that
461 the WM sees it. */
462 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
463 #endif /* 0 */
467 /* Nonzero tells update_wm_hints not to do anything
468 (the caller should call update_wm_hints explicitly later.) */
469 int update_hints_inhibit;
471 static void
472 update_wm_hints (EmacsFrame ew)
474 Widget wmshell = get_wm_shell ((Widget)ew);
475 int cw;
476 int ch;
477 Dimension rounded_width;
478 Dimension rounded_height;
479 int char_width;
480 int char_height;
481 int base_width;
482 int base_height;
483 int min_rows = 0, min_cols = 0;
485 if (update_hints_inhibit)
486 return;
488 #if 0
489 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
490 #endif
492 pixel_to_char_size (ew, ew->core.width, ew->core.height,
493 &char_width, &char_height);
494 char_to_pixel_size (ew, char_width, char_height,
495 &rounded_width, &rounded_height);
496 get_default_char_pixel_size (ew, &cw, &ch);
498 base_width = (wmshell->core.width - ew->core.width
499 + (rounded_width - (char_width * cw)));
500 base_height = (wmshell->core.height - ew->core.height
501 + (rounded_height - (char_height * ch)));
503 /* This is kind of sleazy, but I can't see how else to tell it to
504 make it mark the WM_SIZE_HINTS size as user specified.
506 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
508 XtVaSetValues (wmshell,
509 XtNbaseWidth, (XtArgVal) base_width,
510 XtNbaseHeight, (XtArgVal) base_height,
511 XtNwidthInc, (XtArgVal) cw,
512 XtNheightInc, (XtArgVal) ch,
513 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
514 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
515 NULL);
518 #if 0
520 static void
521 create_frame_gcs (ew)
522 EmacsFrame ew;
524 struct frame *s = ew->emacs_frame.frame;
526 s->output_data.x->normal_gc
527 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
528 (unsigned long)0, (XGCValues *)0);
529 s->output_data.x->reverse_gc
530 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
531 (unsigned long)0, (XGCValues *)0);
532 s->output_data.x->cursor_gc
533 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
534 (unsigned long)0, (XGCValues *)0);
535 s->output_data.x->black_relief.gc = 0;
536 s->output_data.x->white_relief.gc = 0;
539 #endif /* 0 */
541 static char setup_frame_cursor_bits[] =
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
549 static void
550 setup_frame_gcs (EmacsFrame ew)
552 XGCValues gc_values;
553 struct frame* s = ew->emacs_frame.frame;
554 Pixmap blank_stipple, blank_tile;
555 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
556 | GCStipple | GCTile);
557 Lisp_Object font;
559 XSETFONT (font, ew->emacs_frame.font);
560 font = Ffont_xlfd_name (font, Qnil);
561 if (STRINGP (font))
563 XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
564 SDATA (font));
565 if (xfont)
567 gc_values.font = xfont->fid;
568 valuemask |= GCFont;
572 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
573 XGetGCValues returns uninitialized data when we query the stipple
574 (instead of None or something sensible) and it makes things hard.
576 This should be fixed for real by not querying the GCs but instead having
577 some GC-based cache instead of the current face-based cache which doesn't
578 effectively cache all of the GC settings we need to use.
581 blank_stipple
582 = XCreateBitmapFromData (XtDisplay (ew),
583 RootWindowOfScreen (XtScreen (ew)),
584 setup_frame_cursor_bits, 2, 2);
586 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
587 never actually get used as a background tile!
589 blank_tile
590 = XCreatePixmapFromBitmapData (XtDisplay(ew),
591 RootWindowOfScreen (XtScreen (ew)),
592 setup_frame_cursor_bits, 2, 2,
593 (unsigned long)0, (unsigned long)1,
594 ew->core.depth);
596 /* Normal video */
597 gc_values.foreground = ew->emacs_frame.foreground_pixel;
598 gc_values.background = ew->core.background_pixel;
599 gc_values.graphics_exposures = False;
600 gc_values.stipple = blank_stipple;
601 gc_values.tile = blank_tile;
602 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
603 valuemask, &gc_values);
605 /* Reverse video style. */
606 gc_values.foreground = ew->core.background_pixel;
607 gc_values.background = ew->emacs_frame.foreground_pixel;
608 gc_values.graphics_exposures = False;
609 gc_values.stipple = blank_stipple;
610 gc_values.tile = blank_tile;
611 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
612 valuemask, &gc_values);
614 /* Cursor has to have an empty stipple. */
615 gc_values.foreground = ew->core.background_pixel;
616 gc_values.background = ew->emacs_frame.cursor_color;
617 gc_values.graphics_exposures = False;
618 gc_values.tile = blank_tile;
619 gc_values.stipple
620 = XCreateBitmapFromData (XtDisplay (ew),
621 RootWindowOfScreen (XtScreen (ew)),
622 setup_frame_cursor_bits, 16, 16);
623 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
624 valuemask, &gc_values);
627 static void
628 update_various_frame_slots (EmacsFrame ew)
630 struct frame *f = ew->emacs_frame.frame;
631 struct x_output *x = f->output_data.x;
632 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
633 FRAME_PIXEL_WIDTH (f) = ew->core.width;
634 f->internal_border_width = ew->emacs_frame.internal_border_width;
638 static void
639 update_from_various_frame_slots (EmacsFrame ew)
641 struct frame *f = ew->emacs_frame.frame;
642 struct x_output *x = f->output_data.x;
643 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
644 ew->core.width = FRAME_PIXEL_WIDTH (f);
645 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
646 ew->emacs_frame.internal_border_width = f->internal_border_width;
647 ew->emacs_frame.font = x->font;
648 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
649 ew->emacs_frame.cursor_color = x->cursor_pixel;
650 ew->core.border_pixel = x->border_pixel;
653 static void
654 EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
656 EmacsFrame ew = (EmacsFrame)new;
658 if (!ew->emacs_frame.frame)
660 fprintf (stderr,
661 "can't create an emacs frame widget without a frame\n");
662 exit (1);
665 update_from_various_frame_slots (ew);
666 set_frame_size (ew);
670 static void
671 EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
673 EmacsFrame ew = (EmacsFrame)widget;
675 /* This used to contain SubstructureRedirectMask, but this turns out
676 to be a problem with XIM on Solaris, and events from that mask
677 don't seem to be used. Let's check that. */
678 attrs->event_mask = (STANDARD_EVENT_SET
679 | PropertyChangeMask
680 | SubstructureNotifyMask);
681 *mask |= CWEventMask;
682 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
683 attrs);
684 update_wm_hints (ew);
687 extern void free_frame_faces (struct frame *);
689 static void
690 EmacsFrameDestroy (Widget widget)
692 EmacsFrame ew = (EmacsFrame) widget;
693 struct frame* s = ew->emacs_frame.frame;
695 if (! s) abort ();
696 if (! s->output_data.x) abort ();
698 BLOCK_INPUT;
699 x_free_gcs (s);
700 if (s->output_data.x->white_relief.gc)
701 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
702 if (s->output_data.x->black_relief.gc)
703 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
704 UNBLOCK_INPUT;
707 void
708 EmacsFrameResize (Widget widget)
710 EmacsFrame ew = (EmacsFrame)widget;
711 struct frame *f = ew->emacs_frame.frame;
712 int columns;
713 int rows;
715 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
716 change_frame_size (f, rows, columns, 0, 1, 0);
717 update_wm_hints (ew);
718 update_various_frame_slots (ew);
720 cancel_mouse_face (f);
723 static Boolean
724 EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
726 EmacsFrame cur = (EmacsFrame)cur_widget;
727 EmacsFrame new = (EmacsFrame)new_widget;
729 Boolean needs_a_refresh = False;
730 Boolean has_to_recompute_size;
731 Boolean has_to_recompute_gcs;
732 Boolean has_to_update_hints;
734 int char_width, char_height;
735 Dimension pixel_width;
736 Dimension pixel_height;
738 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
739 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
740 || (cur->emacs_frame.foreground_pixel
741 != new->emacs_frame.foreground_pixel)
742 || (cur->core.background_pixel
743 != new->core.background_pixel)
746 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
747 && cur->core.width == new->core.width
748 && cur->core.height == new->core.height);
750 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
752 if (has_to_recompute_gcs)
754 setup_frame_gcs (new);
755 needs_a_refresh = True;
758 if (has_to_recompute_size)
760 pixel_width = new->core.width;
761 pixel_height = new->core.height;
762 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
763 &char_height);
764 char_to_pixel_size (new, char_width, char_height, &pixel_width,
765 &pixel_height);
766 new->core.width = pixel_width;
767 new->core.height = pixel_height;
769 change_frame_size (new->emacs_frame.frame, char_height, char_width,
770 1, 0, 0);
771 needs_a_refresh = True;
774 if (has_to_update_hints)
775 update_wm_hints (new);
777 update_various_frame_slots (new);
779 /* #### This doesn't work, I haven't been able to find ANY kludge that
780 will let (x-create-frame '((iconic . t))) work. It seems that changes
781 to wm_shell's iconic slot have no effect after it has been realized,
782 and calling XIconifyWindow doesn't work either (even though the window
783 has been created.) Perhaps there is some property we could smash
784 directly, but I'm sick of this for now.
786 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
788 Widget wmshell = get_wm_shell ((Widget) cur);
789 XtVaSetValues (wmshell, XtNiconic,
790 (XtArgVal) new->emacs_frame.iconic, NULL);
793 return needs_a_refresh;
796 static XtGeometryResult
797 EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
799 EmacsFrame ew = (EmacsFrame)widget;
801 int mask = request->request_mode;
802 Dimension ok_width, ok_height;
804 if (mask & (CWWidth | CWHeight))
806 round_size_to_char (ew,
807 (mask & CWWidth) ? request->width : ew->core.width,
808 ((mask & CWHeight) ? request->height
809 : ew->core.height),
810 &ok_width, &ok_height);
811 if ((mask & CWWidth) && (ok_width != request->width))
813 result->request_mode |= CWWidth;
814 result->width = ok_width;
816 if ((mask & CWHeight) && (ok_height != request->height))
818 result->request_mode |= CWHeight;
819 result->height = ok_height;
822 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
825 /* Special entrypoints */
826 void
827 EmacsFrameSetCharSize (Widget widget, int columns, int rows)
829 EmacsFrame ew = (EmacsFrame) widget;
830 struct frame *f = ew->emacs_frame.frame;
832 x_set_window_size (f, 0, columns, rows);
836 void
837 widget_store_internal_border (Widget widget)
839 EmacsFrame ew = (EmacsFrame) widget;
840 FRAME_PTR f = ew->emacs_frame.frame;
842 ew->emacs_frame.internal_border_width = f->internal_border_width;
845 /* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
846 (do not change this comment) */