Merge from emacs-24; up to 2012-12-23T02:41:17Z!rgm@gnu.org
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
ab422c4d 2 Copyright (C) 1992-1993, 2000-2013 Free Software Foundation, Inc.
07bf635f
RS
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
07bf635f 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
07bf635f
RS
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
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
07bf635f
RS
18
19/* Emacs 19 face widget ported by Fred Pierresteguy */
20
ac26ca64
KH
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.
25
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/
29 */
30
9e65ad77 31#include <config.h>
565620a5 32#include <stdio.h>
0328b6de 33
07bf635f
RS
34#include "lisp.h"
35#include "xterm.h"
36
87a43646 37#include "keyboard.h"
07bf635f 38#include "frame.h"
dfcf069d 39#include "window.h"
07bf635f
RS
40
41#include "dispextern.h"
49fe12a9 42#include "blockinput.h"
07bf635f
RS
43
44#include <X11/StringDefs.h>
45#include <X11/IntrinsicP.h>
46#include <X11/cursorfont.h>
47#include "widgetprv.h"
65fbf4a3 48#include <X11/ObjectP.h>
07bf635f
RS
49#include <X11/Shell.h>
50#include <X11/ShellP.h>
69524b98 51#include "../lwlib/lwlib.h"
07bf635f 52
39d14c25
CY
53#include "character.h"
54#include "font.h"
55
07bf635f
RS
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
ebd15611
DN
75static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
76static void EmacsFrameDestroy (Widget widget);
77static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
4475bec4 78static void EmacsFrameResize (Widget widget);
ebd15611
DN
79static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
80static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
07bf635f
RS
81
82
83#undef XtOffset
84#define XtOffset(p_type,field) \
85 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
5e617bc2 86#define offset(field) XtOffset (EmacsFrame, emacs_frame.field)
07bf635f
RS
87
88static XtResource resources[] = {
5e617bc2 89 {XtNgeometry, XtCGeometry, XtRString, sizeof (String),
07bf635f 90 offset (geometry), XtRString, (XtPointer) 0},
5e617bc2 91 {XtNiconic, XtCIconic, XtRBoolean, sizeof (Boolean),
07bf635f
RS
92 offset (iconic), XtRImmediate, (XtPointer) False},
93
94 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
95 offset (frame), XtRImmediate, 0},
96
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},
5e617bc2
JB
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"},
07bf635f
RS
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},
117};
118
119#undef offset
120
121/*
122static XtActionsRec
123emacsFrameActionsTable [] = {
124 {"keypress", key_press},
125 {"focus_in", emacs_frame_focus_handler},
126 {"focus_out", emacs_frame_focus_handler},
127};
128
129static char
130emacsFrameTranslations [] = "\
131<KeyPress>: keypress()\n\
132<FocusIn>: focus_in()\n\
133<FocusOut>: focus_out()\n\
134";
135*/
136
4475bec4 137static EmacsFrameClassRec emacsFrameClassRec = {
07bf635f
RS
138 { /* core fields */
139 /* superclass */ &widgetClassRec,
140 /* class_name */ "EmacsFrame",
5e617bc2 141 /* widget_size */ sizeof (EmacsFrameRec),
07bf635f
RS
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,
5e617bc2 151 /* resource_count */ XtNumber (resources),
07bf635f
RS
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
171 }
172};
173
174WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
175
176static void
ebd15611 177get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
07bf635f 178{
07bf635f 179 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
180 *pixel_width = FRAME_COLUMN_WIDTH (f);
181 *pixel_height = FRAME_LINE_HEIGHT (f);
07bf635f
RS
182}
183
184static void
ebd15611 185pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
07bf635f
RS
186{
187 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
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);
07bf635f
RS
190}
191
192static void
ebd15611 193char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
07bf635f
RS
194{
195 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
196 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
197 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
07bf635f
RS
198}
199
200static void
ebd15611 201round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
07bf635f
RS
202{
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);
207}
208
209static Widget
ebd15611 210get_wm_shell (Widget w)
07bf635f
RS
211{
212 Widget wmshell;
213
214 for (wmshell = XtParent (w);
215 wmshell && !XtIsWMShell (wmshell);
216 wmshell = XtParent (wmshell));
217
218 return wmshell;
219}
220
ccce6056
GM
221#if 0 /* Currently not used. */
222
07bf635f 223static void
1dae0f0a 224mark_shell_size_user_specified (Widget wmshell)
07bf635f 225{
1088b922 226 if (! XtIsWMShell (wmshell)) emacs_abort ();
07bf635f
RS
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;
230}
231
ccce6056
GM
232#endif
233
07bf635f
RS
234
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.
240 */
ccce6056 241#if 0
07bf635f 242static Boolean first_frame_p = True;
ccce6056 243#endif
07bf635f
RS
244
245static void
ebd15611 246set_frame_size (EmacsFrame ew)
07bf635f
RS
247{
248 /* The widget hierarchy is
249
250 argv[0] emacsShell pane Frame-NAME
251 ApplicationShell EmacsShell Paned EmacsFrame
252
253 We accept geometry specs in this order:
254
255 *Frame-NAME.geometry
256 *EmacsFrame.geometry
257 Emacs.geometry
258
259 Other possibilities for widget hierarchies might be
260
261 argv[0] frame pane Frame-NAME
262 ApplicationShell EmacsShell Paned EmacsFrame
263 or
264 argv[0] Frame-NAME pane Frame-NAME
265 ApplicationShell EmacsShell Paned EmacsFrame
266 or
267 argv[0] Frame-NAME pane emacsTextPane
268 ApplicationShell EmacsFrame Paned EmacsTextPane
269
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.)
274
177c0ea7 275 The EmacsShell widget is simply a replacement for the Shell widget
07bf635f
RS
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.
280
281 */
282
07bf635f 283 /* Hairily merged geometry */
90022f5a
KS
284 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
285 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
177c0ea7 286
07bf635f 287 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 288 /* Each Emacs shell is now independent and top-level. */
177c0ea7 289
1088b922 290 if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort ();
07bf635f 291
177c0ea7 292 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
293 xfns.c. */
294#if 0
07bf635f
RS
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)
c52e7aa6 299 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
300
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)
c52e7aa6 304 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
177c0ea7
JB
305
306
07bf635f
RS
307 {
308 char *geom = 0;
c52e7aa6 309 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
310 if (geom)
311 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
312 }
177c0ea7 313
07bf635f
RS
314 if (ew->emacs_frame.geometry)
315 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
316 &frame_x, &frame_y,
317 &frame_w, &frame_h);
177c0ea7 318
07bf635f
RS
319 if (first_frame_p)
320 {
321 /* If this is the first frame created:
322 ====================================
323
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")
328
329 - If the AppShell is iconic, the frame should be iconic.
330
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.
334 */
335 if (app_flags & (XValue | YValue))
336 {
337 x = app_x; y = app_y;
338 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
339 }
340 else if (frame_flags & (XValue | YValue))
341 {
342 x = frame_x; y = frame_y;
343 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
344 }
345
346 if (app_flags & (WidthValue | HeightValue))
347 {
348 w = app_w; h = app_h;
349 flags |= (app_flags & (WidthValue | HeightValue));
350 }
351 else if (frame_flags & (WidthValue | HeightValue))
352 {
353 w = frame_w; h = frame_h;
354 flags |= (frame_flags & (WidthValue | HeightValue));
355 }
356
357 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
358 if (!ew->emacs_frame.iconic)
c52e7aa6 359 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
360
361 first_frame_p = False;
362 }
363 else
364 {
365 /* If this is not the first frame created:
366 ========================================
367
368 - use the EmacsFrame's size/position if specified
369 - Otherwise, use the ApplicationShell's size, but not position.
370
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".
374
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.
378 */
379 if (frame_flags & (XValue | YValue))
380 {
381 x = frame_x; y = frame_y;
382 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
383 }
384
385 if (frame_flags & (WidthValue | HeightValue))
386 {
387 w = frame_w; h = frame_h;
388 flags |= (frame_flags & (WidthValue | HeightValue));
389 }
390 else if (app_flags & (WidthValue | HeightValue))
391 {
392 w = app_w;
393 h = app_h;
394 flags |= (app_flags & (WidthValue | HeightValue));
395 }
396 }
edaf359b 397#endif /* 0 */
07bf635f 398 {
90022f5a 399 struct frame *f = ew->emacs_frame.frame;
07bf635f 400 Dimension pixel_width, pixel_height;
07bf635f 401
f403d3c3
GM
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. */
90022f5a
KS
407 f->scroll_bar_actual_width
408 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
07bf635f 409
90022f5a 410 compute_fringe_widths (f, 0);
f403d3c3 411
de70f8b6
RS
412#if 0 /* This can run Lisp code, and it is dangerous to give
413 out the frame to Lisp code before it officially exists.
414 This is handled in Fx_create_frame so not needed here. */
90022f5a 415 change_frame_size (f, h, w, 1, 0, 0);
de70f8b6 416#endif
07bf635f
RS
417 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
418 ew->core.width = pixel_width;
419 ew->core.height = pixel_height;
420
6ae9a3f2 421#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
422 /* If a position was specified, assign it to the shell widget.
423 (Else WM won't do anything with it.)
424 */
425 if (flags & (XValue | YValue))
426 {
427 /* the tricky things with the sign is to make sure that
428 -0 is printed -0. */
07bf635f
RS
429 sprintf (shell_position, "=%c%d%c%d",
430 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
431 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
e99a530f 432 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
07bf635f
RS
433 }
434 else if (flags & (WidthValue | HeightValue))
435 {
07bf635f 436 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
e99a530f 437 XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL);
07bf635f
RS
438 }
439
440 /* If the geometry spec we're using has W/H components, mark the size
441 in the WM_SIZE_HINTS as user specified. */
442 if (flags & (WidthValue | HeightValue))
443 mark_shell_size_user_specified (wmshell);
444
445 /* Also assign the iconic status of the frame to the Shell, so that
446 the WM sees it. */
c52e7aa6 447 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 448#endif /* 0 */
07bf635f
RS
449 }
450}
451
07bf635f 452static void
ebd15611 453update_wm_hints (EmacsFrame ew)
07bf635f
RS
454{
455 Widget wmshell = get_wm_shell ((Widget)ew);
456 int cw;
457 int ch;
458 Dimension rounded_width;
459 Dimension rounded_height;
460 int char_width;
461 int char_height;
462 int base_width;
463 int base_height;
464 int min_rows = 0, min_cols = 0;
465
c052ead4
JD
466 /* This happens when the frame is just created. */
467 if (! wmshell) return;
468
cfcd12d6 469#if 0
07bf635f 470 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 471#endif
07bf635f
RS
472
473 pixel_to_char_size (ew, ew->core.width, ew->core.height,
474 &char_width, &char_height);
475 char_to_pixel_size (ew, char_width, char_height,
476 &rounded_width, &rounded_height);
177c0ea7 477 get_default_char_pixel_size (ew, &cw, &ch);
07bf635f
RS
478
479 base_width = (wmshell->core.width - ew->core.width
480 + (rounded_width - (char_width * cw)));
481 base_height = (wmshell->core.height - ew->core.height
482 + (rounded_height - (char_height * ch)));
483
484 /* This is kind of sleazy, but I can't see how else to tell it to
485 make it mark the WM_SIZE_HINTS size as user specified.
486 */
487/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
488
489 XtVaSetValues (wmshell,
cbec8c51
GM
490 XtNbaseWidth, (XtArgVal) base_width,
491 XtNbaseHeight, (XtArgVal) base_height,
177c0ea7 492 XtNwidthInc, (XtArgVal) cw,
cbec8c51
GM
493 XtNheightInc, (XtArgVal) ch,
494 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
495 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 496 NULL);
07bf635f
RS
497}
498
c052ead4
JD
499void
500widget_update_wm_size_hints (Widget widget)
501{
502 EmacsFrame ew = (EmacsFrame)widget;
503 update_wm_hints (ew);
504}
505
506
ccce6056
GM
507#if 0
508
07bf635f 509static void
1dae0f0a 510create_frame_gcs (EmacsFrame ew)
07bf635f 511{
7f18598b 512 struct frame *s = ew->emacs_frame.frame;
07bf635f 513
54e9e953 514 s->output_data.x->normal_gc
578c21e6 515 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
54e9e953 516 s->output_data.x->reverse_gc
578c21e6 517 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
54e9e953 518 s->output_data.x->cursor_gc
578c21e6 519 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
f403d3c3
GM
520 s->output_data.x->black_relief.gc = 0;
521 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
522}
523
ccce6056
GM
524#endif /* 0 */
525
1ad2277b
RS
526static char setup_frame_cursor_bits[] =
527{
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
532};
533
07bf635f 534static void
ebd15611 535setup_frame_gcs (EmacsFrame ew)
07bf635f
RS
536{
537 XGCValues gc_values;
538 struct frame* s = ew->emacs_frame.frame;
539 Pixmap blank_stipple, blank_tile;
39d14c25
CY
540 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
541 | GCStipple | GCTile);
542 Lisp_Object font;
543
544 XSETFONT (font, ew->emacs_frame.font);
545 font = Ffont_xlfd_name (font, Qnil);
546 if (STRINGP (font))
547 {
548 XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
42a5b22f 549 SSDATA (font));
39d14c25
CY
550 if (xfont)
551 {
552 gc_values.font = xfont->fid;
553 valuemask |= GCFont;
554 }
555 }
07bf635f 556
07bf635f
RS
557 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
558 XGetGCValues returns uninitialized data when we query the stipple
559 (instead of None or something sensible) and it makes things hard.
560
561 This should be fixed for real by not querying the GCs but instead having
562 some GC-based cache instead of the current face-based cache which doesn't
563 effectively cache all of the GC settings we need to use.
564 */
565
85e53327
KH
566 blank_stipple
567 = XCreateBitmapFromData (XtDisplay (ew),
568 RootWindowOfScreen (XtScreen (ew)),
569 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
570
571 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
572 never actually get used as a background tile!
573 */
85e53327 574 blank_tile
5e617bc2 575 = XCreatePixmapFromBitmapData (XtDisplay (ew),
85e53327
KH
576 RootWindowOfScreen (XtScreen (ew)),
577 setup_frame_cursor_bits, 2, 2,
578c21e6 578 0, 1, ew->core.depth);
07bf635f
RS
579
580 /* Normal video */
07bf635f
RS
581 gc_values.foreground = ew->emacs_frame.foreground_pixel;
582 gc_values.background = ew->core.background_pixel;
583 gc_values.graphics_exposures = False;
584 gc_values.stipple = blank_stipple;
585 gc_values.tile = blank_tile;
54e9e953 586 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
39d14c25 587 valuemask, &gc_values);
07bf635f
RS
588
589 /* Reverse video style. */
07bf635f
RS
590 gc_values.foreground = ew->core.background_pixel;
591 gc_values.background = ew->emacs_frame.foreground_pixel;
592 gc_values.graphics_exposures = False;
593 gc_values.stipple = blank_stipple;
594 gc_values.tile = blank_tile;
54e9e953 595 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
39d14c25 596 valuemask, &gc_values);
07bf635f
RS
597
598 /* Cursor has to have an empty stipple. */
07bf635f
RS
599 gc_values.foreground = ew->core.background_pixel;
600 gc_values.background = ew->emacs_frame.cursor_color;
601 gc_values.graphics_exposures = False;
602 gc_values.tile = blank_tile;
85e53327
KH
603 gc_values.stipple
604 = XCreateBitmapFromData (XtDisplay (ew),
605 RootWindowOfScreen (XtScreen (ew)),
606 setup_frame_cursor_bits, 16, 16);
54e9e953 607 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
39d14c25 608 valuemask, &gc_values);
07bf635f
RS
609}
610
611static void
ebd15611 612update_various_frame_slots (EmacsFrame ew)
07bf635f 613{
90022f5a
KS
614 struct frame *f = ew->emacs_frame.frame;
615 struct x_output *x = f->output_data.x;
616 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
617 FRAME_PIXEL_WIDTH (f) = ew->core.width;
618 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
619
620}
621
622static void
ebd15611 623update_from_various_frame_slots (EmacsFrame ew)
07bf635f 624{
90022f5a
KS
625 struct frame *f = ew->emacs_frame.frame;
626 struct x_output *x = f->output_data.x;
627 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
628 ew->core.width = FRAME_PIXEL_WIDTH (f);
ce593f6e 629 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
90022f5a 630 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f 631 ew->emacs_frame.font = x->font;
ce593f6e 632 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
07bf635f
RS
633 ew->emacs_frame.cursor_color = x->cursor_pixel;
634 ew->core.border_pixel = x->border_pixel;
635}
636
177c0ea7 637static void
ebd15611 638EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
07bf635f
RS
639{
640 EmacsFrame ew = (EmacsFrame)new;
641
642 if (!ew->emacs_frame.frame)
643 {
644 fprintf (stderr,
645 "can't create an emacs frame widget without a frame\n");
646 exit (1);
647 }
648
07bf635f 649 update_from_various_frame_slots (ew);
177c0ea7 650 set_frame_size (ew);
07bf635f
RS
651}
652
ad10696b
JD
653static void
654resize_cb (Widget widget,
655 XtPointer closure,
656 XEvent* event,
657 Boolean* continue_to_dispatch)
658{
659 EmacsFrame ew = (EmacsFrame) widget;
660 EmacsFrameResize (widget);
661}
662
07bf635f
RS
663
664static void
ebd15611 665EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
07bf635f
RS
666{
667 EmacsFrame ew = (EmacsFrame)widget;
668
486a103d
GM
669 /* This used to contain SubstructureRedirectMask, but this turns out
670 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 671 don't seem to be used. Let's check that. */
486a103d
GM
672 attrs->event_mask = (STANDARD_EVENT_SET
673 | PropertyChangeMask
674 | SubstructureNotifyMask);
07bf635f
RS
675 *mask |= CWEventMask;
676 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
677 attrs);
ad10696b
JD
678 /* Some ConfigureNotify events does not end up in EmacsFrameResize so
679 make sure we get them all. Seen with xfcwm4 for example. */
680 XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL);
177c0ea7 681 update_wm_hints (ew);
07bf635f
RS
682}
683
07bf635f 684static void
ebd15611 685EmacsFrameDestroy (Widget widget)
07bf635f
RS
686{
687 EmacsFrame ew = (EmacsFrame) widget;
688 struct frame* s = ew->emacs_frame.frame;
689
1088b922
PE
690 if (! s) emacs_abort ();
691 if (! s->output_data.x) emacs_abort ();
07bf635f 692
4d7e6e51 693 block_input ();
0dea0fed 694 x_free_gcs (s);
f403d3c3
GM
695 if (s->output_data.x->white_relief.gc)
696 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
697 if (s->output_data.x->black_relief.gc)
698 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
4d7e6e51 699 unblock_input ();
07bf635f
RS
700}
701
4475bec4 702static void
ebd15611 703EmacsFrameResize (Widget widget)
07bf635f
RS
704{
705 EmacsFrame ew = (EmacsFrame)widget;
706 struct frame *f = ew->emacs_frame.frame;
ad10696b 707 struct x_output *x = f->output_data.x;
07bf635f
RS
708 int columns;
709 int rows;
710
711 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
ad10696b
JD
712 if (columns != FRAME_COLS (f)
713 || rows != FRAME_LINES (f)
714 || ew->core.width != FRAME_PIXEL_WIDTH (f)
715 || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
716 {
717 change_frame_size (f, rows, columns, 0, 1, 0);
718 update_wm_hints (ew);
719 update_various_frame_slots (ew);
49feb47d 720
ad10696b
JD
721 cancel_mouse_face (f);
722 }
07bf635f
RS
723}
724
725static Boolean
ebd15611 726EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
07bf635f
RS
727{
728 EmacsFrame cur = (EmacsFrame)cur_widget;
729 EmacsFrame new = (EmacsFrame)new_widget;
730
731 Boolean needs_a_refresh = False;
732 Boolean has_to_recompute_size;
733 Boolean has_to_recompute_gcs;
734 Boolean has_to_update_hints;
735
736 int char_width, char_height;
737 Dimension pixel_width;
738 Dimension pixel_height;
177c0ea7 739
5c646d5a 740 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
07bf635f
RS
741 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
742 || (cur->emacs_frame.foreground_pixel
743 != new->emacs_frame.foreground_pixel)
744 || (cur->core.background_pixel
745 != new->core.background_pixel)
746 );
177c0ea7 747
07bf635f
RS
748 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
749 && cur->core.width == new->core.width
750 && cur->core.height == new->core.height);
751
752 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
753
754 if (has_to_recompute_gcs)
755 {
756 setup_frame_gcs (new);
757 needs_a_refresh = True;
758 }
177c0ea7 759
07bf635f
RS
760 if (has_to_recompute_size)
761 {
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;
770
771 change_frame_size (new->emacs_frame.frame, char_height, char_width,
2b653806 772 1, 0, 0);
07bf635f
RS
773 needs_a_refresh = True;
774 }
775
776 if (has_to_update_hints)
777 update_wm_hints (new);
778
779 update_various_frame_slots (new);
780
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,
2dd5c7f7 784 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 785 has been created.) Perhaps there is some property we could smash
ac26ca64 786 directly, but I'm sick of this for now.
07bf635f
RS
787 */
788 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
789 {
790 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
791 XtVaSetValues (wmshell, XtNiconic,
792 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
793 }
794
795 return needs_a_refresh;
796}
797
798static XtGeometryResult
ebd15611 799EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
07bf635f
RS
800{
801 EmacsFrame ew = (EmacsFrame)widget;
802
803 int mask = request->request_mode;
804 Dimension ok_width, ok_height;
805
806 if (mask & (CWWidth | CWHeight))
807 {
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))
814 {
815 result->request_mode |= CWWidth;
816 result->width = ok_width;
817 }
818 if ((mask & CWHeight) && (ok_height != request->height))
819 {
820 result->request_mode |= CWHeight;
821 result->height = ok_height;
822 }
823 }
824 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
825}
826
e4769531 827/* Special entry points */
07bf635f 828void
ebd15611 829EmacsFrameSetCharSize (Widget widget, int columns, int rows)
07bf635f
RS
830{
831 EmacsFrame ew = (EmacsFrame) widget;
982a94d9 832 struct frame *f = ew->emacs_frame.frame;
177c0ea7 833
5c646d5a 834 x_set_window_size (f, 0, columns, rows);
07bf635f 835}
f403d3c3 836
d793b105 837\f
dfcf069d 838void
ebd15611 839widget_store_internal_border (Widget widget)
d793b105
RS
840{
841 EmacsFrame ew = (EmacsFrame) widget;
842 FRAME_PTR f = ew->emacs_frame.frame;
843
90022f5a 844 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 845}