Document image-{next, previous}-file, plus some minor tweak.
[emacs.git] / src / widget.c
blob73c5149e2cdd1b385c6db9a02173fa0fe7ac0165
1 /* The emacs frame widget.
2 Copyright (C) 1992-1993, 2000-2013 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 char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
195 struct frame* f = ew->emacs_frame.frame;
196 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
197 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
200 static void
201 round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
203 int char_width;
204 int char_height;
205 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
206 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
209 static Widget
210 get_wm_shell (Widget w)
212 Widget wmshell;
214 for (wmshell = XtParent (w);
215 wmshell && !XtIsWMShell (wmshell);
216 wmshell = XtParent (wmshell));
218 return wmshell;
221 #if 0 /* Currently not used. */
223 static void
224 mark_shell_size_user_specified (Widget wmshell)
226 if (! XtIsWMShell (wmshell)) emacs_abort ();
227 /* This is kind of sleazy, but I can't see how else to tell it to make it
228 mark the WM_SIZE_HINTS size as user specified when appropriate. */
229 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
232 #endif
235 /* Can't have static frame locals because of some broken compilers.
236 Normally, initializing a variable like this doesn't work in emacs,
237 but it's ok in this file because it must come after lastfile (and
238 thus have its data not go into text space) because Xt needs to
239 write to initialized data objects too.
241 #if 0
242 static Boolean first_frame_p = True;
243 #endif
245 static void
246 set_frame_size (EmacsFrame ew)
248 /* The widget hierarchy is
250 argv[0] emacsShell pane Frame-NAME
251 ApplicationShell EmacsShell Paned EmacsFrame
253 We accept geometry specs in this order:
255 *Frame-NAME.geometry
256 *EmacsFrame.geometry
257 Emacs.geometry
259 Other possibilities for widget hierarchies might be
261 argv[0] frame pane Frame-NAME
262 ApplicationShell EmacsShell Paned EmacsFrame
264 argv[0] Frame-NAME pane Frame-NAME
265 ApplicationShell EmacsShell Paned EmacsFrame
267 argv[0] Frame-NAME pane emacsTextPane
268 ApplicationShell EmacsFrame Paned EmacsTextPane
270 With the current setup, the text-display-area is the part which is
271 an emacs "frame", since that's the only part managed by emacs proper
272 (the menubar and the parent of the menubar and all that sort of thing
273 are managed by lwlib.)
275 The EmacsShell widget is simply a replacement for the Shell widget
276 which is able to deal with using an externally-supplied window instead
277 of always creating its own. It is not actually emacs specific, and
278 should possibly have class "Shell" instead of "EmacsShell" to simplify
279 the resources.
283 /* Hairily merged geometry */
284 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
285 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
287 Widget wmshell = get_wm_shell ((Widget) ew);
288 /* Each Emacs shell is now independent and top-level. */
290 if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort ();
292 /* We don't need this for the moment. The geometry is computed in
293 xfns.c. */
294 #if 0
295 /* If the EmacsFrame doesn't have a geometry but the shell does,
296 treat that as the geometry of the frame. (Is this bogus?
297 I'm not sure.) */
298 if (ew->emacs_frame.geometry == 0)
299 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
301 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
302 this bogus? I'm not sure.) */
303 if (!ew->emacs_frame.iconic)
304 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
308 char *geom = 0;
309 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
310 if (geom)
311 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
314 if (ew->emacs_frame.geometry)
315 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
316 &frame_x, &frame_y,
317 &frame_w, &frame_h);
319 if (first_frame_p)
321 /* If this is the first frame created:
322 ====================================
324 - Use the ApplicationShell's size/position, if specified.
325 (This is "Emacs.geometry", or the "-geometry" command line arg.)
326 - Else use the EmacsFrame's size/position.
327 (This is "*Frame-NAME.geometry")
329 - If the AppShell is iconic, the frame should be iconic.
331 AppShell comes first so that -geometry always applies to the first
332 frame created, even if there is an "every frame" entry in the
333 resource database.
335 if (app_flags & (XValue | YValue))
337 x = app_x; y = app_y;
338 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
340 else if (frame_flags & (XValue | YValue))
342 x = frame_x; y = frame_y;
343 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
346 if (app_flags & (WidthValue | HeightValue))
348 w = app_w; h = app_h;
349 flags |= (app_flags & (WidthValue | HeightValue));
351 else if (frame_flags & (WidthValue | HeightValue))
353 w = frame_w; h = frame_h;
354 flags |= (frame_flags & (WidthValue | HeightValue));
357 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
358 if (!ew->emacs_frame.iconic)
359 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
361 first_frame_p = False;
363 else
365 /* If this is not the first frame created:
366 ========================================
368 - use the EmacsFrame's size/position if specified
369 - Otherwise, use the ApplicationShell's size, but not position.
371 So that means that one can specify the position of the first frame
372 with "Emacs.geometry" or `-geometry'; but can only specify the
373 position of subsequent frames with "*Frame-NAME.geometry".
375 AppShell comes second so that -geometry does not apply to subsequent
376 frames when there is an "every frame" entry in the resource db,
377 but does apply to the first frame.
379 if (frame_flags & (XValue | YValue))
381 x = frame_x; y = frame_y;
382 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
385 if (frame_flags & (WidthValue | HeightValue))
387 w = frame_w; h = frame_h;
388 flags |= (frame_flags & (WidthValue | HeightValue));
390 else if (app_flags & (WidthValue | HeightValue))
392 w = app_w;
393 h = app_h;
394 flags |= (app_flags & (WidthValue | HeightValue));
397 #endif /* 0 */
399 struct frame *f = ew->emacs_frame.frame;
400 Dimension pixel_width, pixel_height;
402 /* Take into account the size of the scrollbar. Always use the
403 number of columns occupied by the scroll bar here otherwise we
404 might end up with a frame width that is not a multiple of the
405 frame's character width which is bad for vertically split
406 windows. */
408 compute_fringe_widths (f, 0);
410 #if 0 /* This can run Lisp code, and it is dangerous to give
411 out the frame to Lisp code before it officially exists.
412 This is handled in Fx_create_frame so not needed here. */
413 change_frame_size (f, w, h, 1, 0, 0, 0);
414 #endif
415 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
416 ew->core.width = pixel_width;
417 ew->core.height = pixel_height;
419 #if 0 /* xfns.c takes care of this now. */
420 /* If a position was specified, assign it to the shell widget.
421 (Else WM won't do anything with it.)
423 if (flags & (XValue | YValue))
425 /* the tricky things with the sign is to make sure that
426 -0 is printed -0. */
427 sprintf (shell_position, "=%c%d%c%d",
428 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
429 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
430 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
432 else if (flags & (WidthValue | HeightValue))
434 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
435 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
438 /* If the geometry spec we're using has W/H components, mark the size
439 in the WM_SIZE_HINTS as user specified. */
440 if (flags & (WidthValue | HeightValue))
441 mark_shell_size_user_specified (wmshell);
443 /* Also assign the iconic status of the frame to the Shell, so that
444 the WM sees it. */
445 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
446 #endif /* 0 */
450 static void
451 update_wm_hints (EmacsFrame ew)
453 Widget wmshell = get_wm_shell ((Widget)ew);
454 int cw;
455 int ch;
456 Dimension rounded_width;
457 Dimension rounded_height;
458 int char_width;
459 int char_height;
460 int base_width;
461 int base_height;
462 int min_rows = 0, min_cols = 0;
464 /* This happens when the frame is just created. */
465 if (! wmshell) return;
467 #if 0
468 check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0);
469 #endif
471 pixel_to_char_size (ew, ew->core.width, ew->core.height,
472 &char_width, &char_height);
473 char_to_pixel_size (ew, char_width, char_height,
474 &rounded_width, &rounded_height);
475 get_default_char_pixel_size (ew, &cw, &ch);
477 base_width = (wmshell->core.width - ew->core.width
478 + (rounded_width - (char_width * cw)));
479 base_height = (wmshell->core.height - ew->core.height
480 + (rounded_height - (char_height * ch)));
482 /* This is kind of sleazy, but I can't see how else to tell it to
483 make it mark the WM_SIZE_HINTS size as user specified.
485 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
487 XtVaSetValues (wmshell,
488 XtNbaseWidth, (XtArgVal) base_width,
489 XtNbaseHeight, (XtArgVal) base_height,
490 XtNwidthInc, (XtArgVal) cw,
491 XtNheightInc, (XtArgVal) ch,
492 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
493 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
494 NULL);
497 void
498 widget_update_wm_size_hints (Widget widget)
500 EmacsFrame ew = (EmacsFrame)widget;
501 update_wm_hints (ew);
504 static char setup_frame_cursor_bits[] =
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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
512 static void
513 setup_frame_gcs (EmacsFrame ew)
515 XGCValues gc_values;
516 struct frame* s = ew->emacs_frame.frame;
517 Pixmap blank_stipple, blank_tile;
518 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
519 | GCStipple | GCTile);
520 Lisp_Object font;
522 XSETFONT (font, ew->emacs_frame.font);
523 font = Ffont_xlfd_name (font, Qnil);
524 if (STRINGP (font))
526 XFontStruct *xfont = XLoadQueryFont (FRAME_DISPLAY_INFO (s)->display,
527 SSDATA (font));
528 if (xfont)
530 gc_values.font = xfont->fid;
531 valuemask |= GCFont;
535 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
536 XGetGCValues returns uninitialized data when we query the stipple
537 (instead of None or something sensible) and it makes things hard.
539 This should be fixed for real by not querying the GCs but instead having
540 some GC-based cache instead of the current face-based cache which doesn't
541 effectively cache all of the GC settings we need to use.
544 blank_stipple
545 = XCreateBitmapFromData (XtDisplay (ew),
546 RootWindowOfScreen (XtScreen (ew)),
547 setup_frame_cursor_bits, 2, 2);
549 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
550 never actually get used as a background tile!
552 blank_tile
553 = XCreatePixmapFromBitmapData (XtDisplay (ew),
554 RootWindowOfScreen (XtScreen (ew)),
555 setup_frame_cursor_bits, 2, 2,
556 0, 1, ew->core.depth);
558 /* Normal video */
559 gc_values.foreground = ew->emacs_frame.foreground_pixel;
560 gc_values.background = ew->core.background_pixel;
561 gc_values.graphics_exposures = False;
562 gc_values.stipple = blank_stipple;
563 gc_values.tile = blank_tile;
564 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
565 valuemask, &gc_values);
567 /* Reverse video style. */
568 gc_values.foreground = ew->core.background_pixel;
569 gc_values.background = ew->emacs_frame.foreground_pixel;
570 gc_values.graphics_exposures = False;
571 gc_values.stipple = blank_stipple;
572 gc_values.tile = blank_tile;
573 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
574 valuemask, &gc_values);
576 /* Cursor has to have an empty stipple. */
577 gc_values.foreground = ew->core.background_pixel;
578 gc_values.background = ew->emacs_frame.cursor_color;
579 gc_values.graphics_exposures = False;
580 gc_values.tile = blank_tile;
581 gc_values.stipple
582 = XCreateBitmapFromData (XtDisplay (ew),
583 RootWindowOfScreen (XtScreen (ew)),
584 setup_frame_cursor_bits, 16, 16);
585 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
586 valuemask, &gc_values);
589 static void
590 update_various_frame_slots (EmacsFrame ew)
592 struct frame *f = ew->emacs_frame.frame;
593 struct x_output *x = f->output_data.x;
594 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
595 FRAME_PIXEL_WIDTH (f) = ew->core.width;
596 f->internal_border_width = ew->emacs_frame.internal_border_width;
600 static void
601 update_from_various_frame_slots (EmacsFrame ew)
603 struct frame *f = ew->emacs_frame.frame;
604 struct x_output *x = f->output_data.x;
605 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
606 ew->core.width = FRAME_PIXEL_WIDTH (f);
607 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
608 ew->emacs_frame.internal_border_width = f->internal_border_width;
609 ew->emacs_frame.font = x->font;
610 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
611 ew->emacs_frame.cursor_color = x->cursor_pixel;
612 ew->core.border_pixel = x->border_pixel;
615 static void
616 EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
618 EmacsFrame ew = (EmacsFrame)new;
620 if (!ew->emacs_frame.frame)
622 fprintf (stderr,
623 "can't create an emacs frame widget without a frame\n");
624 exit (1);
627 update_from_various_frame_slots (ew);
628 set_frame_size (ew);
631 static void
632 resize_cb (Widget widget,
633 XtPointer closure,
634 XEvent* event,
635 Boolean* continue_to_dispatch)
637 EmacsFrameResize (widget);
641 static void
642 EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
644 EmacsFrame ew = (EmacsFrame)widget;
646 /* This used to contain SubstructureRedirectMask, but this turns out
647 to be a problem with XIM on Solaris, and events from that mask
648 don't seem to be used. Let's check that. */
649 attrs->event_mask = (STANDARD_EVENT_SET
650 | PropertyChangeMask
651 | SubstructureNotifyMask);
652 *mask |= CWEventMask;
653 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
654 attrs);
655 /* Some ConfigureNotify events does not end up in EmacsFrameResize so
656 make sure we get them all. Seen with xfcwm4 for example. */
657 XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL);
658 update_wm_hints (ew);
661 static void
662 EmacsFrameDestroy (Widget widget)
664 /* All GCs are now freed in x_free_frame_resources. */
667 static void
668 EmacsFrameResize (Widget widget)
670 EmacsFrame ew = (EmacsFrame)widget;
671 struct frame *f = ew->emacs_frame.frame;
672 struct x_output *x = f->output_data.x;
673 int columns;
674 int rows;
676 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
677 if (columns != FRAME_COLS (f)
678 || rows != FRAME_LINES (f)
679 || ew->core.width != FRAME_PIXEL_WIDTH (f)
680 || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
682 change_frame_size (f, columns, rows, 0, 1, 0, 0);
683 update_wm_hints (ew);
684 update_various_frame_slots (ew);
686 cancel_mouse_face (f);
690 static Boolean
691 EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
693 EmacsFrame cur = (EmacsFrame)cur_widget;
694 EmacsFrame new = (EmacsFrame)new_widget;
696 Boolean needs_a_refresh = False;
697 Boolean has_to_recompute_size;
698 Boolean has_to_recompute_gcs;
699 Boolean has_to_update_hints;
701 int char_width, char_height;
702 Dimension pixel_width;
703 Dimension pixel_height;
705 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
706 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
707 || (cur->emacs_frame.foreground_pixel
708 != new->emacs_frame.foreground_pixel)
709 || (cur->core.background_pixel
710 != new->core.background_pixel)
713 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
714 && cur->core.width == new->core.width
715 && cur->core.height == new->core.height);
717 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
719 if (has_to_recompute_gcs)
721 setup_frame_gcs (new);
722 needs_a_refresh = True;
725 if (has_to_recompute_size)
727 pixel_width = new->core.width;
728 pixel_height = new->core.height;
729 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
730 &char_height);
731 char_to_pixel_size (new, char_width, char_height, &pixel_width,
732 &pixel_height);
733 new->core.width = pixel_width;
734 new->core.height = pixel_height;
736 change_frame_size (new->emacs_frame.frame, char_width, char_height,
737 1, 0, 0, 0);
738 needs_a_refresh = True;
741 if (has_to_update_hints)
742 update_wm_hints (new);
744 update_various_frame_slots (new);
746 /* #### This doesn't work, I haven't been able to find ANY kludge that
747 will let (x-create-frame '((iconic . t))) work. It seems that changes
748 to wm_shell's iconic slot have no effect after it has been realized,
749 and calling XIconifyWindow doesn't work either (even though the window
750 has been created.) Perhaps there is some property we could smash
751 directly, but I'm sick of this for now.
753 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
755 Widget wmshell = get_wm_shell ((Widget) cur);
756 XtVaSetValues (wmshell, XtNiconic,
757 (XtArgVal) new->emacs_frame.iconic, NULL);
760 return needs_a_refresh;
763 static XtGeometryResult
764 EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
766 EmacsFrame ew = (EmacsFrame)widget;
768 int mask = request->request_mode;
769 Dimension ok_width, ok_height;
771 if (mask & (CWWidth | CWHeight))
773 round_size_to_char (ew,
774 (mask & CWWidth) ? request->width : ew->core.width,
775 ((mask & CWHeight) ? request->height
776 : ew->core.height),
777 &ok_width, &ok_height);
778 if ((mask & CWWidth) && (ok_width != request->width))
780 result->request_mode |= CWWidth;
781 result->width = ok_width;
783 if ((mask & CWHeight) && (ok_height != request->height))
785 result->request_mode |= CWHeight;
786 result->height = ok_height;
789 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
792 /* Special entry points */
793 void
794 EmacsFrameSetCharSize (Widget widget, int columns, int rows)
796 EmacsFrame ew = (EmacsFrame) widget;
797 struct frame *f = ew->emacs_frame.frame;
799 x_set_window_size (f, 0, columns, rows, 0);
803 void
804 widget_store_internal_border (Widget widget)
806 EmacsFrame ew = (EmacsFrame) widget;
807 struct frame *f = ew->emacs_frame.frame;
809 ew->emacs_frame.internal_border_width = f->internal_border_width;