(EmacsFrameSetCharSize): Set XtNwaitForWm depending
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
0dea0fed 2 Copyright (C) 1992, 1993, 2000 Free Software Foundation, Inc.
07bf635f
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
07bf635f
RS
20
21/* Emacs 19 face widget ported by Fred Pierresteguy */
22
ac26ca64
KH
23/* This file has been censored by the Communications Decency Act.
24 That law was passed under the guise of a ban on pornography, but
25 it bans far more than that. This file did not contain pornography,
26 but it was censored nonetheless.
27
28 For information on US government censorship of the Internet, and
29 what you can do to bring back freedom of the press, see the web
30 site http://www.vtw.org/
31 */
32
9e65ad77 33#include <config.h>
565620a5 34#include <stdio.h>
07bf635f
RS
35#include "lisp.h"
36#include "xterm.h"
37
87a43646 38#include "keyboard.h"
07bf635f 39#include "frame.h"
dfcf069d 40#include "window.h"
07bf635f
RS
41
42#include "dispextern.h"
49fe12a9 43#include "blockinput.h"
07bf635f
RS
44
45#include <X11/StringDefs.h>
46#include <X11/IntrinsicP.h>
47#include <X11/cursorfont.h>
48#include "widgetprv.h"
65fbf4a3 49#include <X11/ObjectP.h>
07bf635f
RS
50#include <X11/Shell.h>
51#include <X11/ShellP.h>
69524b98 52#include "../lwlib/lwlib.h"
07bf635f
RS
53
54#define max(a, b) ((a) > (b) ? (a) : (b))
55
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.
63
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.
69
70 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
71 */
72#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
73
74
01492d1b
RS
75static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
76static void EmacsFrameDestroy (/* Widget */);
77static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
78void EmacsFrameResize (/* Widget widget */);
79static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
80 ArgList, Cardinal * */);
81static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
82 XtWidgetGeometry* */);
07bf635f
RS
83
84
85#undef XtOffset
86#define XtOffset(p_type,field) \
87 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
88#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
89
90static XtResource resources[] = {
91 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
92 offset (geometry), XtRString, (XtPointer) 0},
93 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
94 offset (iconic), XtRImmediate, (XtPointer) False},
95
96 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
97 offset (frame), XtRImmediate, 0},
98
99 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
100 offset (minibuffer), XtRImmediate, (XtPointer)0},
101 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
102 offset (unsplittable), XtRImmediate, (XtPointer)0},
103 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
104 offset (internal_border_width), XtRImmediate, (XtPointer)4},
105 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
106 offset (interline), XtRImmediate, (XtPointer)0},
107 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
108 offset(font),XtRString, DEFAULT_FACE_FONT},
109 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
110 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
111 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
112 offset(cursor_color), XtRString, "XtDefaultForeground"},
113 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
114 offset (bar_cursor), XtRImmediate, (XtPointer)0},
115 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
116 offset (visual_bell), XtRImmediate, (XtPointer)0},
117 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
118 offset (bell_volume), XtRImmediate, (XtPointer)0},
119};
120
121#undef offset
122
123/*
124static XtActionsRec
125emacsFrameActionsTable [] = {
126 {"keypress", key_press},
127 {"focus_in", emacs_frame_focus_handler},
128 {"focus_out", emacs_frame_focus_handler},
129};
130
131static char
132emacsFrameTranslations [] = "\
133<KeyPress>: keypress()\n\
134<FocusIn>: focus_in()\n\
135<FocusOut>: focus_out()\n\
136";
137*/
138
139EmacsFrameClassRec emacsFrameClassRec = {
140 { /* core fields */
141 /* superclass */ &widgetClassRec,
142 /* class_name */ "EmacsFrame",
143 /* widget_size */ sizeof(EmacsFrameRec),
144 /* class_initialize */ 0,
145 /* class_part_initialize */ 0,
146 /* class_inited */ FALSE,
147 /* initialize */ EmacsFrameInitialize,
148 /* initialize_hook */ 0,
149 /* realize */ EmacsFrameRealize,
150 /* actions */ 0, /*emacsFrameActionsTable*/
151 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
152 /* resources */ resources,
153 /* resource_count */ XtNumber(resources),
154 /* xrm_class */ NULLQUARK,
155 /* compress_motion */ TRUE,
156 /* compress_exposure */ TRUE,
157 /* compress_enterleave */ TRUE,
158 /* visible_interest */ FALSE,
159 /* destroy */ EmacsFrameDestroy,
160 /* resize */ EmacsFrameResize,
161 /* expose */ XtInheritExpose,
162 /* set_values */ EmacsFrameSetValues,
163 /* set_values_hook */ 0,
164 /* set_values_almost */ XtInheritSetValuesAlmost,
165 /* get_values_hook */ 0,
166 /* accept_focus */ XtInheritAcceptFocus,
167 /* version */ XtVersion,
168 /* callback_private */ 0,
169 /* tm_table */ 0, /*emacsFrameTranslations*/
170 /* query_geometry */ EmacsFrameQueryGeometry,
171 /* display_accelerator */ XtInheritDisplayAccelerator,
172 /* extension */ 0
173 }
174};
175
176WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
177
178static void
01492d1b
RS
179get_default_char_pixel_size (ew, pixel_width, pixel_height)
180 EmacsFrame ew;
181 int* pixel_width;
182 int* pixel_height;
07bf635f 183{
07bf635f 184 struct frame* f = ew->emacs_frame.frame;
54e9e953
KH
185 *pixel_width = FONT_WIDTH (f->output_data.x->font);
186 *pixel_height = f->output_data.x->line_height;
07bf635f
RS
187}
188
189static void
01492d1b
RS
190pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
191 EmacsFrame ew;
192 Dimension pixel_width;
193 Dimension pixel_height;
194 int* char_width;
195 int* char_height;
07bf635f
RS
196{
197 struct frame* f = ew->emacs_frame.frame;
f8eeed5b
RS
198 *char_width = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
199 *char_height = PIXEL_TO_CHAR_HEIGHT (f, (int) pixel_height);
07bf635f
RS
200}
201
202static void
345a94f9
RS
203char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
204 EmacsFrame ew;
205 int char_width;
206 int char_height;
207 Dimension* pixel_width;
208 Dimension* pixel_height;
07bf635f
RS
209{
210 struct frame* f = ew->emacs_frame.frame;
211 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
212 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
213}
214
215static void
345a94f9
RS
216round_size_to_char (ew, in_width, in_height, out_width, out_height)
217 EmacsFrame ew;
218 Dimension in_width;
219 Dimension in_height;
220 Dimension* out_width;
221 Dimension* out_height;
07bf635f
RS
222{
223 int char_width;
224 int char_height;
225 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
226 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
227}
228
229static Widget
345a94f9
RS
230get_wm_shell (w)
231 Widget w;
07bf635f
RS
232{
233 Widget wmshell;
234
235 for (wmshell = XtParent (w);
236 wmshell && !XtIsWMShell (wmshell);
237 wmshell = XtParent (wmshell));
238
239 return wmshell;
240}
241
ccce6056
GM
242#if 0 /* Currently not used. */
243
07bf635f 244static void
345a94f9
RS
245mark_shell_size_user_specified (wmshell)
246 Widget wmshell;
07bf635f
RS
247{
248 if (! XtIsWMShell (wmshell)) abort ();
249 /* This is kind of sleazy, but I can't see how else to tell it to make it
250 mark the WM_SIZE_HINTS size as user specified when appropriate. */
251 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
252}
253
ccce6056
GM
254#endif
255
07bf635f
RS
256
257/* Can't have static frame locals because of some broken compilers.
258 Normally, initializing a variable like this doesn't work in emacs,
259 but it's ok in this file because it must come after lastfile (and
260 thus have its data not go into text space) because Xt needs to
261 write to initialized data objects too.
262 */
ccce6056 263#if 0
07bf635f 264static Boolean first_frame_p = True;
ccce6056 265#endif
07bf635f
RS
266
267static void
345a94f9
RS
268set_frame_size (ew)
269 EmacsFrame ew;
07bf635f
RS
270{
271 /* The widget hierarchy is
272
273 argv[0] emacsShell pane Frame-NAME
274 ApplicationShell EmacsShell Paned EmacsFrame
275
276 We accept geometry specs in this order:
277
278 *Frame-NAME.geometry
279 *EmacsFrame.geometry
280 Emacs.geometry
281
282 Other possibilities for widget hierarchies might be
283
284 argv[0] frame pane Frame-NAME
285 ApplicationShell EmacsShell Paned EmacsFrame
286 or
287 argv[0] Frame-NAME pane Frame-NAME
288 ApplicationShell EmacsShell Paned EmacsFrame
289 or
290 argv[0] Frame-NAME pane emacsTextPane
291 ApplicationShell EmacsFrame Paned EmacsTextPane
292
293 With the current setup, the text-display-area is the part which is
294 an emacs "frame", since that's the only part managed by emacs proper
295 (the menubar and the parent of the menubar and all that sort of thing
296 are managed by lwlib.)
297
298 The EmacsShell widget is simply a replacement for the Shell widget
299 which is able to deal with using an externally-supplied window instead
300 of always creating its own. It is not actually emacs specific, and
301 should possibly have class "Shell" instead of "EmacsShell" to simplify
302 the resources.
303
304 */
305
07bf635f 306 /* Hairily merged geometry */
07bf635f
RS
307 unsigned int w = ew->emacs_frame.frame->width;
308 unsigned int h = ew->emacs_frame.frame->height;
07bf635f
RS
309
310 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 311 /* Each Emacs shell is now independent and top-level. */
07bf635f 312
07bf635f 313 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 314
8e6208c5 315 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
316 xfns.c. */
317#if 0
07bf635f
RS
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)
c52e7aa6 322 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
323
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)
c52e7aa6 327 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
328
329
330 {
331 char *geom = 0;
c52e7aa6 332 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
333 if (geom)
334 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
335 }
336
337 if (ew->emacs_frame.geometry)
338 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
339 &frame_x, &frame_y,
340 &frame_w, &frame_h);
341
342 if (first_frame_p)
343 {
344 /* If this is the first frame created:
345 ====================================
346
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")
351
352 - If the AppShell is iconic, the frame should be iconic.
353
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.
357 */
358 if (app_flags & (XValue | YValue))
359 {
360 x = app_x; y = app_y;
361 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
362 }
363 else if (frame_flags & (XValue | YValue))
364 {
365 x = frame_x; y = frame_y;
366 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
367 }
368
369 if (app_flags & (WidthValue | HeightValue))
370 {
371 w = app_w; h = app_h;
372 flags |= (app_flags & (WidthValue | HeightValue));
373 }
374 else if (frame_flags & (WidthValue | HeightValue))
375 {
376 w = frame_w; h = frame_h;
377 flags |= (frame_flags & (WidthValue | HeightValue));
378 }
379
380 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
381 if (!ew->emacs_frame.iconic)
c52e7aa6 382 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
383
384 first_frame_p = False;
385 }
386 else
387 {
388 /* If this is not the first frame created:
389 ========================================
390
391 - use the EmacsFrame's size/position if specified
392 - Otherwise, use the ApplicationShell's size, but not position.
393
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".
397
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.
401 */
402 if (frame_flags & (XValue | YValue))
403 {
404 x = frame_x; y = frame_y;
405 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
406 }
407
408 if (frame_flags & (WidthValue | HeightValue))
409 {
410 w = frame_w; h = frame_h;
411 flags |= (frame_flags & (WidthValue | HeightValue));
412 }
413 else if (app_flags & (WidthValue | HeightValue))
414 {
415 w = app_w;
416 h = app_h;
417 flags |= (app_flags & (WidthValue | HeightValue));
418 }
419 }
edaf359b 420#endif /* 0 */
07bf635f
RS
421 {
422 struct frame* frame = ew->emacs_frame.frame;
423 Dimension pixel_width, pixel_height;
07bf635f 424
f403d3c3
GM
425 /* Take into account the size of the scrollbar. Always use the
426 number of columns occupied by the scroll bar here otherwise we
427 might end up with a frame width that is not a multiple of the
428 frame's character width which is bad for vertically split
429 windows. */
54e9e953 430 frame->output_data.x->vertical_scroll_bar_extra
02a162bf
KH
431 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
432 ? 0
02a162bf 433 : (FRAME_SCROLL_BAR_COLS (frame)
54e9e953 434 * FONT_WIDTH (frame->output_data.x->font)));
07bf635f 435
f403d3c3 436 frame->output_data.x->flags_areas_extra
9aa95749 437 = FRAME_FLAGS_AREA_WIDTH (frame);
f403d3c3 438
2b653806 439 change_frame_size (frame, h, w, 1, 0, 0);
07bf635f
RS
440 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
441 ew->core.width = pixel_width;
442 ew->core.height = pixel_height;
443
6ae9a3f2 444#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
445 /* If a position was specified, assign it to the shell widget.
446 (Else WM won't do anything with it.)
447 */
448 if (flags & (XValue | YValue))
449 {
450 /* the tricky things with the sign is to make sure that
451 -0 is printed -0. */
452 int len;
453 char *tem;
454 sprintf (shell_position, "=%c%d%c%d",
455 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
456 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
457 len = strlen (shell_position) + 1;
458 tem = (char *) xmalloc (len);
459 strncpy (tem, shell_position, len);
c52e7aa6 460 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
461 }
462 else if (flags & (WidthValue | HeightValue))
463 {
464 int len;
465 char *tem;
466 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
467 len = strlen (shell_position) + 1;
468 tem = (char *) xmalloc (len);
469 strncpy (tem, shell_position, len);
c52e7aa6 470 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
471 }
472
473 /* If the geometry spec we're using has W/H components, mark the size
474 in the WM_SIZE_HINTS as user specified. */
475 if (flags & (WidthValue | HeightValue))
476 mark_shell_size_user_specified (wmshell);
477
478 /* Also assign the iconic status of the frame to the Shell, so that
479 the WM sees it. */
c52e7aa6 480 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 481#endif /* 0 */
07bf635f
RS
482 }
483}
484
cfcd12d6
KH
485/* Nonzero tells update_wm_hints not to do anything
486 (the caller should call update_wm_hints explicitly later.) */
487int update_hints_inhibit;
07bf635f
RS
488
489static void
345a94f9
RS
490update_wm_hints (ew)
491 EmacsFrame ew;
07bf635f
RS
492{
493 Widget wmshell = get_wm_shell ((Widget)ew);
494 int cw;
495 int ch;
496 Dimension rounded_width;
497 Dimension rounded_height;
498 int char_width;
499 int char_height;
500 int base_width;
501 int base_height;
502 int min_rows = 0, min_cols = 0;
503
cfcd12d6
KH
504 if (update_hints_inhibit)
505 return;
506
507#if 0
07bf635f 508 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 509#endif
07bf635f
RS
510
511 pixel_to_char_size (ew, ew->core.width, ew->core.height,
512 &char_width, &char_height);
513 char_to_pixel_size (ew, char_width, char_height,
514 &rounded_width, &rounded_height);
515 get_default_char_pixel_size (ew, &cw, &ch);
516
517 base_width = (wmshell->core.width - ew->core.width
518 + (rounded_width - (char_width * cw)));
519 base_height = (wmshell->core.height - ew->core.height
520 + (rounded_height - (char_height * ch)));
521
522 /* This is kind of sleazy, but I can't see how else to tell it to
523 make it mark the WM_SIZE_HINTS size as user specified.
524 */
525/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
526
527 XtVaSetValues (wmshell,
cbec8c51
GM
528 XtNbaseWidth, (XtArgVal) base_width,
529 XtNbaseHeight, (XtArgVal) base_height,
530 XtNwidthInc, (XtArgVal) cw,
531 XtNheightInc, (XtArgVal) ch,
532 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
533 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 534 NULL);
07bf635f
RS
535}
536
ccce6056
GM
537#if 0
538
07bf635f 539static void
345a94f9
RS
540create_frame_gcs (ew)
541 EmacsFrame ew;
07bf635f 542{
7f18598b 543 struct frame *s = ew->emacs_frame.frame;
07bf635f 544
54e9e953 545 s->output_data.x->normal_gc
85e53327
KH
546 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
547 (unsigned long)0, (XGCValues *)0);
54e9e953 548 s->output_data.x->reverse_gc
85e53327
KH
549 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
550 (unsigned long)0, (XGCValues *)0);
54e9e953 551 s->output_data.x->cursor_gc
85e53327
KH
552 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
553 (unsigned long)0, (XGCValues *)0);
f403d3c3
GM
554 s->output_data.x->black_relief.gc = 0;
555 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
556}
557
ccce6056
GM
558#endif /* 0 */
559
1ad2277b
RS
560static char setup_frame_cursor_bits[] =
561{
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
566};
567
07bf635f 568static void
345a94f9
RS
569setup_frame_gcs (ew)
570 EmacsFrame ew;
07bf635f
RS
571{
572 XGCValues gc_values;
573 struct frame* s = ew->emacs_frame.frame;
574 Pixmap blank_stipple, blank_tile;
575
07bf635f
RS
576 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
577 XGetGCValues returns uninitialized data when we query the stipple
578 (instead of None or something sensible) and it makes things hard.
579
580 This should be fixed for real by not querying the GCs but instead having
581 some GC-based cache instead of the current face-based cache which doesn't
582 effectively cache all of the GC settings we need to use.
583 */
584
85e53327
KH
585 blank_stipple
586 = XCreateBitmapFromData (XtDisplay (ew),
587 RootWindowOfScreen (XtScreen (ew)),
588 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
589
590 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
591 never actually get used as a background tile!
592 */
85e53327
KH
593 blank_tile
594 = XCreatePixmapFromBitmapData (XtDisplay(ew),
595 RootWindowOfScreen (XtScreen (ew)),
596 setup_frame_cursor_bits, 2, 2,
597 (unsigned long)0, (unsigned long)1,
598 ew->core.depth);
07bf635f
RS
599
600 /* Normal video */
601 gc_values.font = ew->emacs_frame.font->fid;
602 gc_values.foreground = ew->emacs_frame.foreground_pixel;
603 gc_values.background = ew->core.background_pixel;
604 gc_values.graphics_exposures = False;
605 gc_values.stipple = blank_stipple;
606 gc_values.tile = blank_tile;
54e9e953 607 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
07bf635f
RS
608 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
609 | GCStipple | GCTile),
610 &gc_values);
611
612 /* Reverse video style. */
613 gc_values.font = ew->emacs_frame.font->fid;
614 gc_values.foreground = ew->core.background_pixel;
615 gc_values.background = ew->emacs_frame.foreground_pixel;
616 gc_values.graphics_exposures = False;
617 gc_values.stipple = blank_stipple;
618 gc_values.tile = blank_tile;
54e9e953 619 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
07bf635f
RS
620 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
621 | GCStipple | GCTile),
622 &gc_values);
623
624 /* Cursor has to have an empty stipple. */
625 gc_values.font = ew->emacs_frame.font->fid;
626 gc_values.foreground = ew->core.background_pixel;
627 gc_values.background = ew->emacs_frame.cursor_color;
628 gc_values.graphics_exposures = False;
629 gc_values.tile = blank_tile;
85e53327
KH
630 gc_values.stipple
631 = XCreateBitmapFromData (XtDisplay (ew),
632 RootWindowOfScreen (XtScreen (ew)),
633 setup_frame_cursor_bits, 16, 16);
54e9e953 634 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
07bf635f
RS
635 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
636 | GCStipple | GCTile),
637 &gc_values);
638}
639
640static void
345a94f9
RS
641update_various_frame_slots (ew)
642 EmacsFrame ew;
07bf635f 643{
54e9e953 644 struct x_output *x = ew->emacs_frame.frame->output_data.x;
846dd8ae 645 x->pixel_height = ew->core.height + x->menubar_height;
07bf635f
RS
646 x->pixel_width = ew->core.width;
647 x->internal_border_width = ew->emacs_frame.internal_border_width;
648
649}
650
651static void
345a94f9
RS
652update_from_various_frame_slots (ew)
653 EmacsFrame ew;
07bf635f 654{
54e9e953 655 struct x_output *x = ew->emacs_frame.frame->output_data.x;
846dd8ae 656 ew->core.height = x->pixel_height - x->menubar_height;
07bf635f
RS
657 ew->core.width = x->pixel_width;
658 ew->core.background_pixel = x->background_pixel;
659 ew->emacs_frame.internal_border_width = x->internal_border_width;
660 ew->emacs_frame.font = x->font;
661 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
662 ew->emacs_frame.cursor_color = x->cursor_pixel;
663 ew->core.border_pixel = x->border_pixel;
664}
665
666static void
345a94f9
RS
667EmacsFrameInitialize (request, new, dum1, dum2)
668 Widget request;
669 Widget new;
670 ArgList dum1;
671 Cardinal *dum2;
07bf635f
RS
672{
673 EmacsFrame ew = (EmacsFrame)new;
674
675 if (!ew->emacs_frame.frame)
676 {
677 fprintf (stderr,
678 "can't create an emacs frame widget without a frame\n");
679 exit (1);
680 }
681
682#if 0 /* done in xfns.c */
683 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
684 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
685 It's unfortunate that we have to do this, but we need to know the font
686 size for frame-sizing purposes before the faces get initialized. If
687 the "default.attributeFont" isn't set, then we use the font of this
688 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
689 the "default" face will use the frame's font if its own is not set,
690 so everything stays in sync -- it's not possible for the frame's font
691 and the default face's font to be different.
692 */
693 {
694 XFontStruct *f = 0;
695 XtResource face_res;
696 face_res.resource_name = "attributeFont";
697 face_res.resource_class = "AttributeFont";
698 face_res.resource_type = XtRFontStruct;
699 face_res.resource_size = sizeof (XFontStruct *);
700 face_res.resource_offset = 0;
701 face_res.default_type = XtRImmediate;
702 face_res.default_addr = 0;
703 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
704 &face_res, 1, NULL, 0);
705
706 if (f)
707 ew->emacs_frame.font = f;
708 else if (! ew->emacs_frame.font)
709 {
710 fprintf (stderr, "emacs frame widget could not load a font\n");
711 exit (1);
712 }
713 }
714
715/* Update the font field in frame */
54e9e953 716 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
07bf635f
RS
717#endif
718
719 update_from_various_frame_slots (ew);
720 set_frame_size (ew);
721/*create_frame_gcs (ew);
722 setup_frame_gcs (ew);
723 update_various_frame_slots (ew); */
724}
725
726
727static void
345a94f9
RS
728EmacsFrameRealize (widget, mask, attrs)
729 Widget widget;
730 XtValueMask *mask;
731 XSetWindowAttributes *attrs;
07bf635f
RS
732{
733 EmacsFrame ew = (EmacsFrame)widget;
734
486a103d
GM
735 /* This used to contain SubstructureRedirectMask, but this turns out
736 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 737 don't seem to be used. Let's check that. */
486a103d
GM
738 attrs->event_mask = (STANDARD_EVENT_SET
739 | PropertyChangeMask
740 | SubstructureNotifyMask);
07bf635f
RS
741 *mask |= CWEventMask;
742 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
743 attrs);
744 update_wm_hints (ew);
745}
746
345a94f9 747extern void free_frame_faces (/* struct frame * */);
07bf635f
RS
748
749static void
345a94f9
RS
750EmacsFrameDestroy (widget)
751 Widget widget;
07bf635f
RS
752{
753 EmacsFrame ew = (EmacsFrame) widget;
754 struct frame* s = ew->emacs_frame.frame;
755
756 if (! s) abort ();
54e9e953
KH
757 if (! s->output_data.x) abort ();
758 if (! s->output_data.x->normal_gc) abort ();
07bf635f 759
49fe12a9 760 BLOCK_INPUT;
0dea0fed 761 x_free_gcs (s);
f403d3c3
GM
762 if (s->output_data.x->white_relief.gc)
763 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
764 if (s->output_data.x->black_relief.gc)
765 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
49fe12a9 766 UNBLOCK_INPUT;
07bf635f
RS
767}
768
769void
345a94f9
RS
770EmacsFrameResize (widget)
771 Widget widget;
07bf635f
RS
772{
773 EmacsFrame ew = (EmacsFrame)widget;
774 struct frame *f = ew->emacs_frame.frame;
775 int columns;
776 int rows;
777
778 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
2b653806 779 change_frame_size (f, rows, columns, 0, 1, 0);
07bf635f 780 update_wm_hints (ew);
07bf635f 781 update_various_frame_slots (ew);
49feb47d
RS
782
783 cancel_mouse_face (f);
07bf635f
RS
784}
785
786static Boolean
345a94f9
RS
787EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
788 Widget cur_widget;
789 Widget req_widget;
790 Widget new_widget;
791 ArgList dum1;
792 Cardinal *dum2;
07bf635f
RS
793{
794 EmacsFrame cur = (EmacsFrame)cur_widget;
795 EmacsFrame new = (EmacsFrame)new_widget;
796
797 Boolean needs_a_refresh = False;
798 Boolean has_to_recompute_size;
799 Boolean has_to_recompute_gcs;
800 Boolean has_to_update_hints;
801
802 int char_width, char_height;
803 Dimension pixel_width;
804 Dimension pixel_height;
805
806 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
807 || (cur->emacs_frame.foreground_pixel
808 != new->emacs_frame.foreground_pixel)
809 || (cur->core.background_pixel
810 != new->core.background_pixel)
811 );
812
813 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
814 && cur->core.width == new->core.width
815 && cur->core.height == new->core.height);
816
817 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
818
819 if (has_to_recompute_gcs)
820 {
821 setup_frame_gcs (new);
822 needs_a_refresh = True;
823 }
824
825 if (has_to_recompute_size)
826 {
827 pixel_width = new->core.width;
828 pixel_height = new->core.height;
829 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
830 &char_height);
831 char_to_pixel_size (new, char_width, char_height, &pixel_width,
832 &pixel_height);
833 new->core.width = pixel_width;
834 new->core.height = pixel_height;
835
836 change_frame_size (new->emacs_frame.frame, char_height, char_width,
2b653806 837 1, 0, 0);
07bf635f
RS
838 needs_a_refresh = True;
839 }
840
841 if (has_to_update_hints)
842 update_wm_hints (new);
843
844 update_various_frame_slots (new);
845
846 /* #### This doesn't work, I haven't been able to find ANY kludge that
847 will let (x-create-frame '((iconic . t))) work. It seems that changes
848 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 849 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 850 has been created.) Perhaps there is some property we could smash
ac26ca64 851 directly, but I'm sick of this for now.
07bf635f
RS
852 */
853 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
854 {
855 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
856 XtVaSetValues (wmshell, XtNiconic,
857 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
858 }
859
860 return needs_a_refresh;
861}
862
863static XtGeometryResult
345a94f9
RS
864EmacsFrameQueryGeometry (widget, request, result)
865 Widget widget;
866 XtWidgetGeometry* request;
867 XtWidgetGeometry* result;
07bf635f
RS
868{
869 EmacsFrame ew = (EmacsFrame)widget;
870
871 int mask = request->request_mode;
872 Dimension ok_width, ok_height;
873
874 if (mask & (CWWidth | CWHeight))
875 {
876 round_size_to_char (ew,
877 (mask & CWWidth) ? request->width : ew->core.width,
878 ((mask & CWHeight) ? request->height
879 : ew->core.height),
880 &ok_width, &ok_height);
881 if ((mask & CWWidth) && (ok_width != request->width))
882 {
883 result->request_mode |= CWWidth;
884 result->width = ok_width;
885 }
886 if ((mask & CWHeight) && (ok_height != request->height))
887 {
888 result->request_mode |= CWHeight;
889 result->height = ok_height;
890 }
891 }
892 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
893}
894
07bf635f
RS
895/* Special entrypoints */
896void
345a94f9
RS
897EmacsFrameSetCharSize (widget, columns, rows)
898 Widget widget;
899 int columns;
900 int rows;
07bf635f
RS
901{
902 EmacsFrame ew = (EmacsFrame) widget;
ccce6056 903 Dimension pixel_width, pixel_height;
982a94d9 904 struct frame *f = ew->emacs_frame.frame;
b3ccf2a2 905
07bf635f 906 if (columns < 3) columns = 3; /* no way buddy */
07bf635f 907
982a94d9 908 check_frame_size (f, &rows, &columns);
54e9e953 909 f->output_data.x->vertical_scroll_bar_extra
02a162bf
KH
910 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
911 ? 0
54e9e953 912 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
02a162bf 913
f403d3c3 914 f->output_data.x->flags_areas_extra
9aa95749 915 = FRAME_FLAGS_AREA_WIDTH (f);
f403d3c3 916
203ae560
GM
917 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
918
919#if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
f403d3c3
GM
920 /* Something is really strange here wrt to the border width:
921 Apparently, XtNwidth and XtNheight include the border, so we have
922 to add it here. But the XtNborderWidth set for the widgets has
923 no similarity to what f->output_data.x->border_width is set to. */
f403d3c3
GM
924 XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
925 pixel_height += 2 * border_width;
926 pixel_width += 2 * border_width;
203ae560
GM
927#endif
928
cfcd12d6
KH
929 /* Manually change the height and width of all our widgets,
930 adjusting each widget by the same increments. */
f403d3c3
GM
931 if (ew->core.width != pixel_width
932 || ew->core.height != pixel_height)
07bf635f 933 {
57aa60d8 934 int hdelta = pixel_height - ew->core.height;
cfcd12d6 935 int wdelta = pixel_width - ew->core.width;
54e9e953
KH
936 int column_widget_height = f->output_data.x->column_widget->core.height;
937 int column_widget_width = f->output_data.x->column_widget->core.width;
938 int outer_widget_height = f->output_data.x->widget->core.height;
939 int outer_widget_width = f->output_data.x->widget->core.width;
940 int old_left = f->output_data.x->widget->core.x;
941 int old_top = f->output_data.x->widget->core.y;
942
cbec8c51
GM
943 /* Input is blocked here, and Xt waits for some event to
944 occur. */
945
54e9e953 946 lw_refigure_widget (f->output_data.x->column_widget, False);
cfcd12d6
KH
947 update_hints_inhibit = 1;
948
cbec8c51
GM
949 /* Xt waits for a ConfigureNotify event from the window manager
950 in EmacsFrameSetCharSize when the shell widget is resized.
951 For some window managers like fvwm2 2.2.5 and KDE 2.1 this
952 event doesn't arrive for an unknown reason and Emacs hangs in
953 Xt when the default font is changed. Tell Xt not to wait,
954 depending on the value of the frame parameter
955 `wait-for-wm'. */
956 XtVaSetValues (f->output_data.x->widget,
957 XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
958 NULL);
959
6e7e15f2
GM
960 /* Do parents first, otherwise LessTif's geometry management
961 enters an infinite loop (as of 2000-01-15). This is fixed in
962 later versions of LessTif (as of 2001-03-13); I'll leave it
963 as is because I think it can't do any harm. */
47d09164 964 XtVaSetValues (f->output_data.x->widget,
cbec8c51
GM
965 XtNheight, (XtArgVal) (outer_widget_height + hdelta),
966 XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
967 NULL);
47d09164 968 XtVaSetValues (f->output_data.x->column_widget,
cbec8c51
GM
969 XtNheight, (XtArgVal) (column_widget_height + hdelta),
970 XtNwidth, (XtArgVal) column_widget_width + wdelta,
971 NULL);
47d09164 972 XtVaSetValues ((Widget) ew,
cbec8c51
GM
973 XtNheight, (XtArgVal) pixel_height,
974 XtNwidth, (XtArgVal) pixel_width,
975 NULL);
b3ccf2a2 976
54e9e953 977 lw_refigure_widget (f->output_data.x->column_widget, True);
50d5aeb5 978
cfcd12d6
KH
979 update_hints_inhibit = 0;
980 update_wm_hints (ew);
981
50d5aeb5 982 /* These seem to get clobbered. I don't know why. - rms. */
54e9e953
KH
983 f->output_data.x->widget->core.x = old_left;
984 f->output_data.x->widget->core.y = old_top;
07bf635f 985 }
982a94d9
FP
986
987 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
988 receive in the ConfigureNotify event; if we get what we asked
989 for, then the event won't cause the screen to become garbaged, so
990 we have to make sure to do it here. */
991 SET_FRAME_GARBAGED (f);
07bf635f 992}
f403d3c3 993
d793b105 994\f
dfcf069d 995void
d793b105
RS
996widget_store_internal_border (widget)
997 Widget widget;
998{
999 EmacsFrame ew = (EmacsFrame) widget;
1000 FRAME_PTR f = ew->emacs_frame.frame;
1001
1002 ew->emacs_frame.internal_border_width
1003 = f->output_data.x->internal_border_width;
1004}