Correct loop termination condition in c-syntactic-skip-backward.
[emacs.git] / src / widget.c
blob45118a887307d392a20f5e85a52cd9f213749e49
1 /* The emacs frame widget.
2 Copyright (C) 1992-1993, 2000-2014 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 3 of the License, or
9 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
19 /* Emacs 19 face widget ported by Fred Pierresteguy */
21 /* This file has been censored by the Communications Decency Act.
22 That law was passed under the guise of a ban on pornography, but
23 it bans far more than that. This file did not contain pornography,
24 but it was censored nonetheless.
26 For information on US government censorship of the Internet, and
27 what you can do to bring back freedom of the press, see the web
28 site http://www.vtw.org/
31 #include <config.h>
32 #include <stdio.h>
34 #include "lisp.h"
35 #include "xterm.h"
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "window.h"
41 #include "dispextern.h"
42 #include "blockinput.h"
44 #include <X11/StringDefs.h>
45 #include <X11/IntrinsicP.h>
46 #include <X11/cursorfont.h>
47 #include "widgetprv.h"
48 #include <X11/ObjectP.h>
49 #include <X11/Shell.h>
50 #include <X11/ShellP.h>
51 #include "../lwlib/lwlib.h"
53 #include "character.h"
54 #include "font.h"
56 /* This sucks: this is the first default that x-faces.el tries. This won't
57 be used unless neither the "Emacs.EmacsFrame" resource nor the
58 "Emacs.EmacsFrame" resource is set; the frame
59 may have the wrong default size if this font doesn't exist, but some other
60 font that x-faces.el does. The workaround is to specify some font in the
61 resource database; I don't know a solution other than duplicating the font-
62 searching code from x-faces.el in this file.
64 This also means that if "Emacs.EmacsFrame" is specified as a non-
65 existent font, then Xt is going to substitute "XtDefaultFont" for it,
66 which is a different size than this one. The solution for this is to
67 make x-faces.el try to use XtDefaultFont. The problem with that is that
68 XtDefaultFont is almost certainly variable-width.
70 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
72 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
75 static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
76 static void EmacsFrameDestroy (Widget widget);
77 static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
78 static void EmacsFrameResize (Widget widget);
79 static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
80 static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
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 (struct font *),
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 static 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 (EmacsFrame ew, int *pixel_width, int *pixel_height)
179 struct frame* f = ew->emacs_frame.frame;
180 *pixel_width = FRAME_COLUMN_WIDTH (f);
181 *pixel_height = FRAME_LINE_HEIGHT (f);
184 static void
185 pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
187 struct frame* f = ew->emacs_frame.frame;
188 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
189 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
192 static void
193 pixel_to_text_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *text_width, int *text_height)
195 struct frame* f = ew->emacs_frame.frame;
196 *text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, (int) pixel_width);
197 *text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, (int) pixel_height);
200 static void
201 char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
203 struct frame* f = ew->emacs_frame.frame;
204 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
205 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
208 static void
209 round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, 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 (Widget w)
220 Widget wmshell;
222 for (wmshell = XtParent (w);
223 wmshell && !XtIsWMShell (wmshell);
224 wmshell = XtParent (wmshell));
226 return wmshell;
229 #if 0 /* Currently not used. */
231 static void
232 mark_shell_size_user_specified (Widget wmshell)
234 if (! XtIsWMShell (wmshell)) emacs_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;
240 #endif
243 /* Can't have static frame locals because of some broken compilers.
244 Normally, initializing a variable like this doesn't work in emacs,
245 but it's ok in this file because it must come after lastfile (and
246 thus have its data not go into text space) because Xt needs to
247 write to initialized data objects too.
249 #if 0
250 static Boolean first_frame_p = True;
251 #endif
253 static void
254 set_frame_size (EmacsFrame ew)
256 /* The widget hierarchy is
258 argv[0] emacsShell pane Frame-NAME
259 ApplicationShell EmacsShell Paned EmacsFrame
261 We accept geometry specs in this order:
263 *Frame-NAME.geometry
264 *EmacsFrame.geometry
265 Emacs.geometry
267 Other possibilities for widget hierarchies might be
269 argv[0] frame pane Frame-NAME
270 ApplicationShell EmacsShell Paned EmacsFrame
272 argv[0] Frame-NAME pane Frame-NAME
273 ApplicationShell EmacsShell Paned EmacsFrame
275 argv[0] Frame-NAME pane emacsTextPane
276 ApplicationShell EmacsFrame Paned EmacsTextPane
278 With the current setup, the text-display-area is the part which is
279 an emacs "frame", since that's the only part managed by emacs proper
280 (the menubar and the parent of the menubar and all that sort of thing
281 are managed by lwlib.)
283 The EmacsShell widget is simply a replacement for the Shell widget
284 which is able to deal with using an externally-supplied window instead
285 of always creating its own. It is not actually emacs specific, and
286 should possibly have class "Shell" instead of "EmacsShell" to simplify
287 the resources.
291 /* Hairily merged geometry */
292 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
293 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
295 Widget wmshell = get_wm_shell ((Widget) ew);
296 /* Each Emacs shell is now independent and top-level. */
298 if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort ();
300 /* We don't need this for the moment. The geometry is computed in
301 xfns.c. */
302 #if 0
303 /* If the EmacsFrame doesn't have a geometry but the shell does,
304 treat that as the geometry of the frame. (Is this bogus?
305 I'm not sure.) */
306 if (ew->emacs_frame.geometry == 0)
307 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
309 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
310 this bogus? I'm not sure.) */
311 if (!ew->emacs_frame.iconic)
312 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
316 char *geom = 0;
317 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
318 if (geom)
319 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
322 if (ew->emacs_frame.geometry)
323 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
324 &frame_x, &frame_y,
325 &frame_w, &frame_h);
327 if (first_frame_p)
329 /* If this is the first frame created:
330 ====================================
332 - Use the ApplicationShell's size/position, if specified.
333 (This is "Emacs.geometry", or the "-geometry" command line arg.)
334 - Else use the EmacsFrame's size/position.
335 (This is "*Frame-NAME.geometry")
337 - If the AppShell is iconic, the frame should be iconic.
339 AppShell comes first so that -geometry always applies to the first
340 frame created, even if there is an "every frame" entry in the
341 resource database.
343 if (app_flags & (XValue | YValue))
345 x = app_x; y = app_y;
346 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
348 else if (frame_flags & (XValue | YValue))
350 x = frame_x; y = frame_y;
351 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
354 if (app_flags & (WidthValue | HeightValue))
356 w = app_w; h = app_h;
357 flags |= (app_flags & (WidthValue | HeightValue));
359 else if (frame_flags & (WidthValue | HeightValue))
361 w = frame_w; h = frame_h;
362 flags |= (frame_flags & (WidthValue | HeightValue));
365 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
366 if (!ew->emacs_frame.iconic)
367 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
369 first_frame_p = False;
371 else
373 /* If this is not the first frame created:
374 ========================================
376 - use the EmacsFrame's size/position if specified
377 - Otherwise, use the ApplicationShell's size, but not position.
379 So that means that one can specify the position of the first frame
380 with "Emacs.geometry" or `-geometry'; but can only specify the
381 position of subsequent frames with "*Frame-NAME.geometry".
383 AppShell comes second so that -geometry does not apply to subsequent
384 frames when there is an "every frame" entry in the resource db,
385 but does apply to the first frame.
387 if (frame_flags & (XValue | YValue))
389 x = frame_x; y = frame_y;
390 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
393 if (frame_flags & (WidthValue | HeightValue))
395 w = frame_w; h = frame_h;
396 flags |= (frame_flags & (WidthValue | HeightValue));
398 else if (app_flags & (WidthValue | HeightValue))
400 w = app_w;
401 h = app_h;
402 flags |= (app_flags & (WidthValue | HeightValue));
405 #endif /* 0 */
407 Dimension pixel_width, pixel_height;
409 /* Take into account the size of the scrollbar. Always use the
410 number of columns occupied by the scroll bar here otherwise we
411 might end up with a frame width that is not a multiple of the
412 frame's character width which is bad for vertically split
413 windows. */
415 #if 0 /* This can run Lisp code, and it is dangerous to give
416 out the frame to Lisp code before it officially exists.
417 This is handled in Fx_create_frame so not needed here. */
418 change_frame_size (f, w, h, 1, 0, 0, 0);
419 #endif
420 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
421 ew->core.width = pixel_width;
422 ew->core.height = pixel_height;
424 #if 0 /* xfns.c takes care of this now. */
425 /* If a position was specified, assign it to the shell widget.
426 (Else WM won't do anything with it.)
428 if (flags & (XValue | YValue))
430 /* the tricky things with the sign is to make sure that
431 -0 is printed -0. */
432 sprintf (shell_position, "=%c%d%c%d",
433 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
434 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
435 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
437 else if (flags & (WidthValue | HeightValue))
439 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
440 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
443 /* If the geometry spec we're using has W/H components, mark the size
444 in the WM_SIZE_HINTS as user specified. */
445 if (flags & (WidthValue | HeightValue))
446 mark_shell_size_user_specified (wmshell);
448 /* Also assign the iconic status of the frame to the Shell, so that
449 the WM sees it. */
450 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
451 #endif /* 0 */
455 static void
456 update_wm_hints (EmacsFrame ew)
458 Widget wmshell = get_wm_shell ((Widget)ew);
459 int cw;
460 int ch;
461 Dimension rounded_width;
462 Dimension rounded_height;
463 int char_width;
464 int char_height;
465 int base_width;
466 int base_height;
467 int min_rows = 0, min_cols = 0;
469 /* This happens when the frame is just created. */
470 if (! wmshell) return;
472 pixel_to_char_size (ew, ew->core.width, ew->core.height,
473 &char_width, &char_height);
474 char_to_pixel_size (ew, char_width, char_height,
475 &rounded_width, &rounded_height);
476 get_default_char_pixel_size (ew, &cw, &ch);
478 base_width = (wmshell->core.width - ew->core.width
479 + (rounded_width - (char_width * cw)));
480 base_height = (wmshell->core.height - ew->core.height
481 + (rounded_height - (char_height * ch)));
483 /* This is kind of sleazy, but I can't see how else to tell it to
484 make it mark the WM_SIZE_HINTS size as user specified.
486 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
488 XtVaSetValues (wmshell,
489 XtNbaseWidth, (XtArgVal) base_width,
490 XtNbaseHeight, (XtArgVal) base_height,
491 XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw),
492 XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch),
493 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
494 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
495 NULL);
498 void
499 widget_update_wm_size_hints (Widget widget)
501 EmacsFrame ew = (EmacsFrame)widget;
502 update_wm_hints (ew);
505 static char setup_frame_cursor_bits[] =
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
513 static void
514 setup_frame_gcs (EmacsFrame ew)
516 XGCValues gc_values;
517 struct frame* s = ew->emacs_frame.frame;
518 Pixmap blank_stipple, blank_tile;
519 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
520 | GCStipple | GCTile);
521 Lisp_Object font;
523 XSETFONT (font, ew->emacs_frame.font);
524 font = Ffont_xlfd_name (font, Qnil);
525 if (STRINGP (font))
527 XFontStruct *xfont = XLoadQueryFont (FRAME_DISPLAY_INFO (s)->display,
528 SSDATA (font));
529 if (xfont)
531 gc_values.font = xfont->fid;
532 valuemask |= GCFont;
536 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
537 XGetGCValues returns uninitialized data when we query the stipple
538 (instead of None or something sensible) and it makes things hard.
540 This should be fixed for real by not querying the GCs but instead having
541 some GC-based cache instead of the current face-based cache which doesn't
542 effectively cache all of the GC settings we need to use.
545 blank_stipple
546 = XCreateBitmapFromData (XtDisplay (ew),
547 RootWindowOfScreen (XtScreen (ew)),
548 setup_frame_cursor_bits, 2, 2);
550 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
551 never actually get used as a background tile!
553 blank_tile
554 = XCreatePixmapFromBitmapData (XtDisplay (ew),
555 RootWindowOfScreen (XtScreen (ew)),
556 setup_frame_cursor_bits, 2, 2,
557 0, 1, ew->core.depth);
559 /* Normal video */
560 gc_values.foreground = ew->emacs_frame.foreground_pixel;
561 gc_values.background = ew->core.background_pixel;
562 gc_values.graphics_exposures = False;
563 gc_values.stipple = blank_stipple;
564 gc_values.tile = blank_tile;
565 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
566 valuemask, &gc_values);
568 /* Reverse video style. */
569 gc_values.foreground = ew->core.background_pixel;
570 gc_values.background = ew->emacs_frame.foreground_pixel;
571 gc_values.graphics_exposures = False;
572 gc_values.stipple = blank_stipple;
573 gc_values.tile = blank_tile;
574 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
575 valuemask, &gc_values);
577 /* Cursor has to have an empty stipple. */
578 gc_values.foreground = ew->core.background_pixel;
579 gc_values.background = ew->emacs_frame.cursor_color;
580 gc_values.graphics_exposures = False;
581 gc_values.tile = blank_tile;
582 gc_values.stipple
583 = XCreateBitmapFromData (XtDisplay (ew),
584 RootWindowOfScreen (XtScreen (ew)),
585 setup_frame_cursor_bits, 16, 16);
586 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
587 valuemask, &gc_values);
590 static void
591 update_various_frame_slots (EmacsFrame ew)
593 struct frame *f = ew->emacs_frame.frame;
595 /* Don't do that: It confuses the check in change_frame_size_1 whether
596 the pixel size of the frame changed due to a change of the internal
597 border width. Bug#16736. */
598 if (false)
600 struct x_output *x = f->output_data.x;
601 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
602 FRAME_PIXEL_WIDTH (f) = ew->core.width;
605 f->internal_border_width = ew->emacs_frame.internal_border_width;
608 static void
609 update_from_various_frame_slots (EmacsFrame ew)
611 struct frame *f = ew->emacs_frame.frame;
612 struct x_output *x = f->output_data.x;
613 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
614 ew->core.width = FRAME_PIXEL_WIDTH (f);
615 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
616 ew->emacs_frame.internal_border_width = f->internal_border_width;
617 ew->emacs_frame.font = x->font;
618 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
619 ew->emacs_frame.cursor_color = x->cursor_pixel;
620 ew->core.border_pixel = x->border_pixel;
623 static void
624 EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
626 EmacsFrame ew = (EmacsFrame)new;
628 if (!ew->emacs_frame.frame)
630 fprintf (stderr,
631 "can't create an emacs frame widget without a frame\n");
632 exit (1);
635 update_from_various_frame_slots (ew);
636 set_frame_size (ew);
639 static void
640 resize_cb (Widget widget,
641 XtPointer closure,
642 XEvent* event,
643 Boolean* continue_to_dispatch)
645 EmacsFrameResize (widget);
649 static void
650 EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
652 EmacsFrame ew = (EmacsFrame)widget;
654 /* This used to contain SubstructureRedirectMask, but this turns out
655 to be a problem with XIM on Solaris, and events from that mask
656 don't seem to be used. Let's check that. */
657 attrs->event_mask = (STANDARD_EVENT_SET
658 | PropertyChangeMask
659 | SubstructureNotifyMask);
660 *mask |= CWEventMask;
661 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
662 attrs);
663 /* Some ConfigureNotify events does not end up in EmacsFrameResize so
664 make sure we get them all. Seen with xfcwm4 for example. */
665 XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL);
666 update_wm_hints (ew);
669 static void
670 EmacsFrameDestroy (Widget widget)
672 /* All GCs are now freed in x_free_frame_resources. */
675 static void
676 EmacsFrameResize (Widget widget)
678 EmacsFrame ew = (EmacsFrame)widget;
679 struct frame *f = ew->emacs_frame.frame;
681 /* Always process resize requests pixelwise. Frame maximizing
682 should work even when frame_resize_pixelwise is nil. */
683 if (true || frame_resize_pixelwise)
685 int width, height;
686 /** int width = (ew->core.width **/
687 /** - FRAME_SCROLL_BAR_AREA_WIDTH (f) **/
688 /** - FRAME_TOTAL_FRINGE_WIDTH (f) **/
689 /** - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
691 /** int height = (ew->core.height **/
692 /** - FRAME_TOOLBAR_HEIGHT (f) **/
693 /** - FRAME_SCROLL_BAR_AREA_HEIGHT (f) **/
694 /** - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); **/
696 pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
697 change_frame_size (f, width, height, 0, 1, 0, 1);
699 update_wm_hints (ew);
700 update_various_frame_slots (ew);
702 cancel_mouse_face (f);
704 else
706 struct x_output *x = f->output_data.x;
707 int columns, rows;
709 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
710 if (columns != FRAME_COLS (f)
711 || rows != FRAME_LINES (f)
712 || ew->core.width != FRAME_PIXEL_WIDTH (f)
713 || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
715 change_frame_size (f, columns, rows, 0, 1, 0, 0);
716 update_wm_hints (ew);
717 update_various_frame_slots (ew);
719 cancel_mouse_face (f);
724 static Boolean
725 EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
727 EmacsFrame cur = (EmacsFrame)cur_widget;
728 EmacsFrame new = (EmacsFrame)new_widget;
730 Boolean needs_a_refresh = False;
731 Boolean has_to_recompute_size;
732 Boolean has_to_recompute_gcs;
733 Boolean has_to_update_hints;
735 int char_width, char_height;
736 Dimension pixel_width;
737 Dimension pixel_height;
739 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
740 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
741 || (cur->emacs_frame.foreground_pixel
742 != new->emacs_frame.foreground_pixel)
743 || (cur->core.background_pixel
744 != new->core.background_pixel)
747 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
748 && cur->core.width == new->core.width
749 && cur->core.height == new->core.height);
751 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
753 if (has_to_recompute_gcs)
755 setup_frame_gcs (new);
756 needs_a_refresh = True;
759 if (has_to_recompute_size)
761 /* Don't do this pixelwise, hopefully. */
762 pixel_width = new->core.width;
763 pixel_height = new->core.height;
764 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
765 &char_height);
766 char_to_pixel_size (new, char_width, char_height, &pixel_width,
767 &pixel_height);
768 new->core.width = pixel_width;
769 new->core.height = pixel_height;
771 change_frame_size (new->emacs_frame.frame, char_width, char_height,
772 1, 0, 0, 0);
773 needs_a_refresh = True;
776 if (has_to_update_hints)
777 update_wm_hints (new);
779 update_various_frame_slots (new);
781 /* #### This doesn't work, I haven't been able to find ANY kludge that
782 will let (x-create-frame '((iconic . t))) work. It seems that changes
783 to wm_shell's iconic slot have no effect after it has been realized,
784 and calling XIconifyWindow doesn't work either (even though the window
785 has been created.) Perhaps there is some property we could smash
786 directly, but I'm sick of this for now.
788 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
790 Widget wmshell = get_wm_shell ((Widget) cur);
791 XtVaSetValues (wmshell, XtNiconic,
792 (XtArgVal) new->emacs_frame.iconic, NULL);
795 return needs_a_refresh;
798 static XtGeometryResult
799 EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
801 EmacsFrame ew = (EmacsFrame)widget;
803 int mask = request->request_mode;
804 Dimension ok_width, ok_height;
806 if (mask & (CWWidth | CWHeight))
808 round_size_to_char (ew,
809 (mask & CWWidth) ? request->width : ew->core.width,
810 ((mask & CWHeight) ? request->height
811 : ew->core.height),
812 &ok_width, &ok_height);
813 if ((mask & CWWidth) && (ok_width != request->width))
815 result->request_mode |= CWWidth;
816 result->width = ok_width;
818 if ((mask & CWHeight) && (ok_height != request->height))
820 result->request_mode |= CWHeight;
821 result->height = ok_height;
824 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
827 /* Special entry points */
828 void
829 EmacsFrameSetCharSize (Widget widget, int columns, int rows)
831 EmacsFrame ew = (EmacsFrame) widget;
832 struct frame *f = ew->emacs_frame.frame;
834 if (!frame_inhibit_resize (f, 0) && !frame_inhibit_resize (f, 1))
835 x_set_window_size (f, 0, columns, rows, 0);
839 void
840 widget_store_internal_border (Widget widget)
842 EmacsFrame ew = (EmacsFrame) widget;
843 struct frame *f = ew->emacs_frame.frame;
845 ew->emacs_frame.internal_border_width = f->internal_border_width;