Merge from trunk
[bpt/emacs.git] / src / widget.c
CommitLineData
07bf635f 1/* The emacs frame widget.
429ab54e 2 Copyright (C) 1992, 1993, 2000, 2001, 2002, 2003, 2004,
114f9c96 3 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
07bf635f
RS
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
07bf635f 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
07bf635f
RS
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
07bf635f
RS
19
20/* Emacs 19 face widget ported by Fred Pierresteguy */
21
ac26ca64
KH
22/* This file has been censored by the Communications Decency Act.
23 That law was passed under the guise of a ban on pornography, but
24 it bans far more than that. This file did not contain pornography,
25 but it was censored nonetheless.
26
27 For information on US government censorship of the Internet, and
28 what you can do to bring back freedom of the press, see the web
29 site http://www.vtw.org/
30 */
31
9e65ad77 32#include <config.h>
565620a5 33#include <stdio.h>
d7306fe6 34#include <setjmp.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 53
a5d3ec3f
GM
54#include <signal.h>
55#include "syssignal.h"
56
39d14c25
CY
57#include "character.h"
58#include "font.h"
59
07bf635f
RS
60/* This sucks: this is the first default that x-faces.el tries. This won't
61 be used unless neither the "Emacs.EmacsFrame" resource nor the
62 "Emacs.EmacsFrame" resource is set; the frame
63 may have the wrong default size if this font doesn't exist, but some other
64 font that x-faces.el does. The workaround is to specify some font in the
65 resource database; I don't know a solution other than duplicating the font-
66 searching code from x-faces.el in this file.
67
68 This also means that if "Emacs.EmacsFrame" is specified as a non-
69 existent font, then Xt is going to substitute "XtDefaultFont" for it,
70 which is a different size than this one. The solution for this is to
71 make x-faces.el try to use XtDefaultFont. The problem with that is that
72 XtDefaultFont is almost certainly variable-width.
73
74 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
75 */
76#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
77
78
ebd15611
DN
79static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
80static void EmacsFrameDestroy (Widget widget);
81static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
82void EmacsFrameResize (Widget widget);
83static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
84static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
07bf635f
RS
85
86
87#undef XtOffset
88#define XtOffset(p_type,field) \
89 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
90#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
91
92static XtResource resources[] = {
93 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
94 offset (geometry), XtRString, (XtPointer) 0},
95 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
96 offset (iconic), XtRImmediate, (XtPointer) False},
97
98 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
99 offset (frame), XtRImmediate, 0},
100
101 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
102 offset (minibuffer), XtRImmediate, (XtPointer)0},
103 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
104 offset (unsplittable), XtRImmediate, (XtPointer)0},
105 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
106 offset (internal_border_width), XtRImmediate, (XtPointer)4},
107 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
108 offset (interline), XtRImmediate, (XtPointer)0},
39d14c25 109 {XtNfont, XtCFont, XtRFontStruct, sizeof(struct font *),
07bf635f
RS
110 offset(font),XtRString, DEFAULT_FACE_FONT},
111 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
112 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
113 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
114 offset(cursor_color), XtRString, "XtDefaultForeground"},
115 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
116 offset (bar_cursor), XtRImmediate, (XtPointer)0},
117 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
118 offset (visual_bell), XtRImmediate, (XtPointer)0},
119 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
120 offset (bell_volume), XtRImmediate, (XtPointer)0},
121};
122
123#undef offset
124
125/*
126static XtActionsRec
127emacsFrameActionsTable [] = {
128 {"keypress", key_press},
129 {"focus_in", emacs_frame_focus_handler},
130 {"focus_out", emacs_frame_focus_handler},
131};
132
133static char
134emacsFrameTranslations [] = "\
135<KeyPress>: keypress()\n\
136<FocusIn>: focus_in()\n\
137<FocusOut>: focus_out()\n\
138";
139*/
140
141EmacsFrameClassRec emacsFrameClassRec = {
142 { /* core fields */
143 /* superclass */ &widgetClassRec,
144 /* class_name */ "EmacsFrame",
145 /* widget_size */ sizeof(EmacsFrameRec),
146 /* class_initialize */ 0,
147 /* class_part_initialize */ 0,
148 /* class_inited */ FALSE,
149 /* initialize */ EmacsFrameInitialize,
150 /* initialize_hook */ 0,
151 /* realize */ EmacsFrameRealize,
152 /* actions */ 0, /*emacsFrameActionsTable*/
153 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
154 /* resources */ resources,
155 /* resource_count */ XtNumber(resources),
156 /* xrm_class */ NULLQUARK,
157 /* compress_motion */ TRUE,
158 /* compress_exposure */ TRUE,
159 /* compress_enterleave */ TRUE,
160 /* visible_interest */ FALSE,
161 /* destroy */ EmacsFrameDestroy,
162 /* resize */ EmacsFrameResize,
163 /* expose */ XtInheritExpose,
164 /* set_values */ EmacsFrameSetValues,
165 /* set_values_hook */ 0,
166 /* set_values_almost */ XtInheritSetValuesAlmost,
167 /* get_values_hook */ 0,
168 /* accept_focus */ XtInheritAcceptFocus,
169 /* version */ XtVersion,
170 /* callback_private */ 0,
171 /* tm_table */ 0, /*emacsFrameTranslations*/
172 /* query_geometry */ EmacsFrameQueryGeometry,
173 /* display_accelerator */ XtInheritDisplayAccelerator,
174 /* extension */ 0
175 }
176};
177
178WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
179
180static void
ebd15611 181get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
07bf635f 182{
07bf635f 183 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
184 *pixel_width = FRAME_COLUMN_WIDTH (f);
185 *pixel_height = FRAME_LINE_HEIGHT (f);
07bf635f
RS
186}
187
188static void
ebd15611 189pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
07bf635f
RS
190{
191 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
192 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
193 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
07bf635f
RS
194}
195
196static void
ebd15611 197char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
07bf635f
RS
198{
199 struct frame* f = ew->emacs_frame.frame;
90022f5a
KS
200 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
201 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
07bf635f
RS
202}
203
204static void
ebd15611 205round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
07bf635f
RS
206{
207 int char_width;
208 int char_height;
209 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
210 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
211}
212
213static Widget
ebd15611 214get_wm_shell (Widget w)
07bf635f
RS
215{
216 Widget wmshell;
217
218 for (wmshell = XtParent (w);
219 wmshell && !XtIsWMShell (wmshell);
220 wmshell = XtParent (wmshell));
221
222 return wmshell;
223}
224
ccce6056
GM
225#if 0 /* Currently not used. */
226
07bf635f 227static void
345a94f9
RS
228mark_shell_size_user_specified (wmshell)
229 Widget wmshell;
07bf635f
RS
230{
231 if (! XtIsWMShell (wmshell)) abort ();
232 /* This is kind of sleazy, but I can't see how else to tell it to make it
233 mark the WM_SIZE_HINTS size as user specified when appropriate. */
234 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
235}
236
ccce6056
GM
237#endif
238
07bf635f
RS
239
240/* Can't have static frame locals because of some broken compilers.
241 Normally, initializing a variable like this doesn't work in emacs,
242 but it's ok in this file because it must come after lastfile (and
243 thus have its data not go into text space) because Xt needs to
244 write to initialized data objects too.
245 */
ccce6056 246#if 0
07bf635f 247static Boolean first_frame_p = True;
ccce6056 248#endif
07bf635f
RS
249
250static void
ebd15611 251set_frame_size (EmacsFrame ew)
07bf635f
RS
252{
253 /* The widget hierarchy is
254
255 argv[0] emacsShell pane Frame-NAME
256 ApplicationShell EmacsShell Paned EmacsFrame
257
258 We accept geometry specs in this order:
259
260 *Frame-NAME.geometry
261 *EmacsFrame.geometry
262 Emacs.geometry
263
264 Other possibilities for widget hierarchies might be
265
266 argv[0] frame pane Frame-NAME
267 ApplicationShell EmacsShell Paned EmacsFrame
268 or
269 argv[0] Frame-NAME pane Frame-NAME
270 ApplicationShell EmacsShell Paned EmacsFrame
271 or
272 argv[0] Frame-NAME pane emacsTextPane
273 ApplicationShell EmacsFrame Paned EmacsTextPane
274
275 With the current setup, the text-display-area is the part which is
276 an emacs "frame", since that's the only part managed by emacs proper
277 (the menubar and the parent of the menubar and all that sort of thing
278 are managed by lwlib.)
279
177c0ea7 280 The EmacsShell widget is simply a replacement for the Shell widget
07bf635f
RS
281 which is able to deal with using an externally-supplied window instead
282 of always creating its own. It is not actually emacs specific, and
283 should possibly have class "Shell" instead of "EmacsShell" to simplify
284 the resources.
285
286 */
287
07bf635f 288 /* Hairily merged geometry */
90022f5a
KS
289 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
290 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
177c0ea7 291
07bf635f 292 Widget wmshell = get_wm_shell ((Widget) ew);
38971c41 293 /* Each Emacs shell is now independent and top-level. */
177c0ea7 294
07bf635f 295 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
07bf635f 296
177c0ea7 297 /* We don't need this for the moment. The geometry is computed in
edaf359b
FP
298 xfns.c. */
299#if 0
07bf635f
RS
300 /* If the EmacsFrame doesn't have a geometry but the shell does,
301 treat that as the geometry of the frame. (Is this bogus?
302 I'm not sure.) */
303 if (ew->emacs_frame.geometry == 0)
c52e7aa6 304 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
07bf635f
RS
305
306 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
307 this bogus? I'm not sure.) */
308 if (!ew->emacs_frame.iconic)
c52e7aa6 309 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
177c0ea7
JB
310
311
07bf635f
RS
312 {
313 char *geom = 0;
c52e7aa6 314 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
07bf635f
RS
315 if (geom)
316 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
317 }
177c0ea7 318
07bf635f
RS
319 if (ew->emacs_frame.geometry)
320 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
321 &frame_x, &frame_y,
322 &frame_w, &frame_h);
177c0ea7 323
07bf635f
RS
324 if (first_frame_p)
325 {
326 /* If this is the first frame created:
327 ====================================
328
329 - Use the ApplicationShell's size/position, if specified.
330 (This is "Emacs.geometry", or the "-geometry" command line arg.)
331 - Else use the EmacsFrame's size/position.
332 (This is "*Frame-NAME.geometry")
333
334 - If the AppShell is iconic, the frame should be iconic.
335
336 AppShell comes first so that -geometry always applies to the first
337 frame created, even if there is an "every frame" entry in the
338 resource database.
339 */
340 if (app_flags & (XValue | YValue))
341 {
342 x = app_x; y = app_y;
343 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
344 }
345 else if (frame_flags & (XValue | YValue))
346 {
347 x = frame_x; y = frame_y;
348 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
349 }
350
351 if (app_flags & (WidthValue | HeightValue))
352 {
353 w = app_w; h = app_h;
354 flags |= (app_flags & (WidthValue | HeightValue));
355 }
356 else if (frame_flags & (WidthValue | HeightValue))
357 {
358 w = frame_w; h = frame_h;
359 flags |= (frame_flags & (WidthValue | HeightValue));
360 }
361
362 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
363 if (!ew->emacs_frame.iconic)
c52e7aa6 364 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
07bf635f
RS
365
366 first_frame_p = False;
367 }
368 else
369 {
370 /* If this is not the first frame created:
371 ========================================
372
373 - use the EmacsFrame's size/position if specified
374 - Otherwise, use the ApplicationShell's size, but not position.
375
376 So that means that one can specify the position of the first frame
377 with "Emacs.geometry" or `-geometry'; but can only specify the
378 position of subsequent frames with "*Frame-NAME.geometry".
379
380 AppShell comes second so that -geometry does not apply to subsequent
381 frames when there is an "every frame" entry in the resource db,
382 but does apply to the first frame.
383 */
384 if (frame_flags & (XValue | YValue))
385 {
386 x = frame_x; y = frame_y;
387 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
388 }
389
390 if (frame_flags & (WidthValue | HeightValue))
391 {
392 w = frame_w; h = frame_h;
393 flags |= (frame_flags & (WidthValue | HeightValue));
394 }
395 else if (app_flags & (WidthValue | HeightValue))
396 {
397 w = app_w;
398 h = app_h;
399 flags |= (app_flags & (WidthValue | HeightValue));
400 }
401 }
edaf359b 402#endif /* 0 */
07bf635f 403 {
90022f5a 404 struct frame *f = ew->emacs_frame.frame;
07bf635f 405 Dimension pixel_width, pixel_height;
07bf635f 406
f403d3c3
GM
407 /* Take into account the size of the scrollbar. Always use the
408 number of columns occupied by the scroll bar here otherwise we
409 might end up with a frame width that is not a multiple of the
410 frame's character width which is bad for vertically split
411 windows. */
90022f5a
KS
412 f->scroll_bar_actual_width
413 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
07bf635f 414
90022f5a 415 compute_fringe_widths (f, 0);
f403d3c3 416
de70f8b6
RS
417#if 0 /* This can run Lisp code, and it is dangerous to give
418 out the frame to Lisp code before it officially exists.
419 This is handled in Fx_create_frame so not needed here. */
90022f5a 420 change_frame_size (f, h, w, 1, 0, 0);
de70f8b6 421#endif
07bf635f
RS
422 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
423 ew->core.width = pixel_width;
424 ew->core.height = pixel_height;
425
6ae9a3f2 426#if 0 /* xfns.c takes care of this now. */
07bf635f
RS
427 /* If a position was specified, assign it to the shell widget.
428 (Else WM won't do anything with it.)
429 */
430 if (flags & (XValue | YValue))
431 {
432 /* the tricky things with the sign is to make sure that
433 -0 is printed -0. */
434 int len;
435 char *tem;
436 sprintf (shell_position, "=%c%d%c%d",
437 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
438 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
439 len = strlen (shell_position) + 1;
440 tem = (char *) xmalloc (len);
441 strncpy (tem, shell_position, len);
c52e7aa6 442 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
443 }
444 else if (flags & (WidthValue | HeightValue))
445 {
446 int len;
447 char *tem;
448 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
449 len = strlen (shell_position) + 1;
450 tem = (char *) xmalloc (len);
451 strncpy (tem, shell_position, len);
c52e7aa6 452 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
07bf635f
RS
453 }
454
455 /* If the geometry spec we're using has W/H components, mark the size
456 in the WM_SIZE_HINTS as user specified. */
457 if (flags & (WidthValue | HeightValue))
458 mark_shell_size_user_specified (wmshell);
459
460 /* Also assign the iconic status of the frame to the Shell, so that
461 the WM sees it. */
c52e7aa6 462 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
edaf359b 463#endif /* 0 */
07bf635f
RS
464 }
465}
466
cfcd12d6
KH
467/* Nonzero tells update_wm_hints not to do anything
468 (the caller should call update_wm_hints explicitly later.) */
469int update_hints_inhibit;
07bf635f
RS
470
471static void
ebd15611 472update_wm_hints (EmacsFrame ew)
07bf635f
RS
473{
474 Widget wmshell = get_wm_shell ((Widget)ew);
475 int cw;
476 int ch;
477 Dimension rounded_width;
478 Dimension rounded_height;
479 int char_width;
480 int char_height;
481 int base_width;
482 int base_height;
483 int min_rows = 0, min_cols = 0;
484
cfcd12d6
KH
485 if (update_hints_inhibit)
486 return;
487
488#if 0
07bf635f 489 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
cfcd12d6 490#endif
07bf635f
RS
491
492 pixel_to_char_size (ew, ew->core.width, ew->core.height,
493 &char_width, &char_height);
494 char_to_pixel_size (ew, char_width, char_height,
495 &rounded_width, &rounded_height);
177c0ea7 496 get_default_char_pixel_size (ew, &cw, &ch);
07bf635f
RS
497
498 base_width = (wmshell->core.width - ew->core.width
499 + (rounded_width - (char_width * cw)));
500 base_height = (wmshell->core.height - ew->core.height
501 + (rounded_height - (char_height * ch)));
502
503 /* This is kind of sleazy, but I can't see how else to tell it to
504 make it mark the WM_SIZE_HINTS size as user specified.
505 */
506/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
507
508 XtVaSetValues (wmshell,
cbec8c51
GM
509 XtNbaseWidth, (XtArgVal) base_width,
510 XtNbaseHeight, (XtArgVal) base_height,
177c0ea7 511 XtNwidthInc, (XtArgVal) cw,
cbec8c51
GM
512 XtNheightInc, (XtArgVal) ch,
513 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
514 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
c52e7aa6 515 NULL);
07bf635f
RS
516}
517
ccce6056
GM
518#if 0
519
07bf635f 520static void
345a94f9
RS
521create_frame_gcs (ew)
522 EmacsFrame ew;
07bf635f 523{
7f18598b 524 struct frame *s = ew->emacs_frame.frame;
07bf635f 525
54e9e953 526 s->output_data.x->normal_gc
85e53327
KH
527 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
528 (unsigned long)0, (XGCValues *)0);
54e9e953 529 s->output_data.x->reverse_gc
85e53327
KH
530 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
531 (unsigned long)0, (XGCValues *)0);
54e9e953 532 s->output_data.x->cursor_gc
85e53327
KH
533 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
534 (unsigned long)0, (XGCValues *)0);
f403d3c3
GM
535 s->output_data.x->black_relief.gc = 0;
536 s->output_data.x->white_relief.gc = 0;
07bf635f
RS
537}
538
ccce6056
GM
539#endif /* 0 */
540
1ad2277b
RS
541static char setup_frame_cursor_bits[] =
542{
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
547};
548
07bf635f 549static void
ebd15611 550setup_frame_gcs (EmacsFrame ew)
07bf635f
RS
551{
552 XGCValues gc_values;
553 struct frame* s = ew->emacs_frame.frame;
554 Pixmap blank_stipple, blank_tile;
39d14c25
CY
555 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
556 | GCStipple | GCTile);
557 Lisp_Object font;
558
559 XSETFONT (font, ew->emacs_frame.font);
560 font = Ffont_xlfd_name (font, Qnil);
561 if (STRINGP (font))
562 {
563 XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
564 SDATA (font));
565 if (xfont)
566 {
567 gc_values.font = xfont->fid;
568 valuemask |= GCFont;
569 }
570 }
07bf635f 571
07bf635f
RS
572 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
573 XGetGCValues returns uninitialized data when we query the stipple
574 (instead of None or something sensible) and it makes things hard.
575
576 This should be fixed for real by not querying the GCs but instead having
577 some GC-based cache instead of the current face-based cache which doesn't
578 effectively cache all of the GC settings we need to use.
579 */
580
85e53327
KH
581 blank_stipple
582 = XCreateBitmapFromData (XtDisplay (ew),
583 RootWindowOfScreen (XtScreen (ew)),
584 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
585
586 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
587 never actually get used as a background tile!
588 */
85e53327
KH
589 blank_tile
590 = XCreatePixmapFromBitmapData (XtDisplay(ew),
591 RootWindowOfScreen (XtScreen (ew)),
592 setup_frame_cursor_bits, 2, 2,
593 (unsigned long)0, (unsigned long)1,
594 ew->core.depth);
07bf635f
RS
595
596 /* Normal video */
07bf635f
RS
597 gc_values.foreground = ew->emacs_frame.foreground_pixel;
598 gc_values.background = ew->core.background_pixel;
599 gc_values.graphics_exposures = False;
600 gc_values.stipple = blank_stipple;
601 gc_values.tile = blank_tile;
54e9e953 602 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
39d14c25 603 valuemask, &gc_values);
07bf635f
RS
604
605 /* Reverse video style. */
07bf635f
RS
606 gc_values.foreground = ew->core.background_pixel;
607 gc_values.background = ew->emacs_frame.foreground_pixel;
608 gc_values.graphics_exposures = False;
609 gc_values.stipple = blank_stipple;
610 gc_values.tile = blank_tile;
54e9e953 611 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
39d14c25 612 valuemask, &gc_values);
07bf635f
RS
613
614 /* Cursor has to have an empty stipple. */
07bf635f
RS
615 gc_values.foreground = ew->core.background_pixel;
616 gc_values.background = ew->emacs_frame.cursor_color;
617 gc_values.graphics_exposures = False;
618 gc_values.tile = blank_tile;
85e53327
KH
619 gc_values.stipple
620 = XCreateBitmapFromData (XtDisplay (ew),
621 RootWindowOfScreen (XtScreen (ew)),
622 setup_frame_cursor_bits, 16, 16);
54e9e953 623 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
39d14c25 624 valuemask, &gc_values);
07bf635f
RS
625}
626
627static void
ebd15611 628update_various_frame_slots (EmacsFrame ew)
07bf635f 629{
90022f5a
KS
630 struct frame *f = ew->emacs_frame.frame;
631 struct x_output *x = f->output_data.x;
632 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
633 FRAME_PIXEL_WIDTH (f) = ew->core.width;
634 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
635
636}
637
638static void
ebd15611 639update_from_various_frame_slots (EmacsFrame ew)
07bf635f 640{
90022f5a
KS
641 struct frame *f = ew->emacs_frame.frame;
642 struct x_output *x = f->output_data.x;
643 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
644 ew->core.width = FRAME_PIXEL_WIDTH (f);
ce593f6e 645 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
90022f5a 646 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f 647 ew->emacs_frame.font = x->font;
ce593f6e 648 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
07bf635f
RS
649 ew->emacs_frame.cursor_color = x->cursor_pixel;
650 ew->core.border_pixel = x->border_pixel;
651}
652
177c0ea7 653static void
ebd15611 654EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
07bf635f
RS
655{
656 EmacsFrame ew = (EmacsFrame)new;
657
658 if (!ew->emacs_frame.frame)
659 {
660 fprintf (stderr,
661 "can't create an emacs frame widget without a frame\n");
662 exit (1);
663 }
664
07bf635f 665 update_from_various_frame_slots (ew);
177c0ea7 666 set_frame_size (ew);
07bf635f
RS
667}
668
669
670static void
ebd15611 671EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
07bf635f
RS
672{
673 EmacsFrame ew = (EmacsFrame)widget;
674
486a103d
GM
675 /* This used to contain SubstructureRedirectMask, but this turns out
676 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 677 don't seem to be used. Let's check that. */
486a103d
GM
678 attrs->event_mask = (STANDARD_EVENT_SET
679 | PropertyChangeMask
680 | SubstructureNotifyMask);
07bf635f
RS
681 *mask |= CWEventMask;
682 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
683 attrs);
177c0ea7 684 update_wm_hints (ew);
07bf635f
RS
685}
686
ebd15611 687extern void free_frame_faces (struct frame *);
07bf635f
RS
688
689static void
ebd15611 690EmacsFrameDestroy (Widget widget)
07bf635f
RS
691{
692 EmacsFrame ew = (EmacsFrame) widget;
693 struct frame* s = ew->emacs_frame.frame;
694
695 if (! s) abort ();
54e9e953 696 if (! s->output_data.x) abort ();
07bf635f 697
49fe12a9 698 BLOCK_INPUT;
0dea0fed 699 x_free_gcs (s);
f403d3c3
GM
700 if (s->output_data.x->white_relief.gc)
701 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
702 if (s->output_data.x->black_relief.gc)
703 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
49fe12a9 704 UNBLOCK_INPUT;
07bf635f
RS
705}
706
707void
ebd15611 708EmacsFrameResize (Widget widget)
07bf635f
RS
709{
710 EmacsFrame ew = (EmacsFrame)widget;
711 struct frame *f = ew->emacs_frame.frame;
712 int columns;
713 int rows;
714
715 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
2b653806 716 change_frame_size (f, rows, columns, 0, 1, 0);
177c0ea7 717 update_wm_hints (ew);
07bf635f 718 update_various_frame_slots (ew);
49feb47d
RS
719
720 cancel_mouse_face (f);
07bf635f
RS
721}
722
723static Boolean
ebd15611 724EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
07bf635f
RS
725{
726 EmacsFrame cur = (EmacsFrame)cur_widget;
727 EmacsFrame new = (EmacsFrame)new_widget;
728
729 Boolean needs_a_refresh = False;
730 Boolean has_to_recompute_size;
731 Boolean has_to_recompute_gcs;
732 Boolean has_to_update_hints;
733
734 int char_width, char_height;
735 Dimension pixel_width;
736 Dimension pixel_height;
177c0ea7 737
5c646d5a 738 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
07bf635f
RS
739 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
740 || (cur->emacs_frame.foreground_pixel
741 != new->emacs_frame.foreground_pixel)
742 || (cur->core.background_pixel
743 != new->core.background_pixel)
744 );
177c0ea7 745
07bf635f
RS
746 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
747 && cur->core.width == new->core.width
748 && cur->core.height == new->core.height);
749
750 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
751
752 if (has_to_recompute_gcs)
753 {
754 setup_frame_gcs (new);
755 needs_a_refresh = True;
756 }
177c0ea7 757
07bf635f
RS
758 if (has_to_recompute_size)
759 {
760 pixel_width = new->core.width;
761 pixel_height = new->core.height;
762 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
763 &char_height);
764 char_to_pixel_size (new, char_width, char_height, &pixel_width,
765 &pixel_height);
766 new->core.width = pixel_width;
767 new->core.height = pixel_height;
768
769 change_frame_size (new->emacs_frame.frame, char_height, char_width,
2b653806 770 1, 0, 0);
07bf635f
RS
771 needs_a_refresh = True;
772 }
773
774 if (has_to_update_hints)
775 update_wm_hints (new);
776
777 update_various_frame_slots (new);
778
779 /* #### This doesn't work, I haven't been able to find ANY kludge that
780 will let (x-create-frame '((iconic . t))) work. It seems that changes
781 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 782 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 783 has been created.) Perhaps there is some property we could smash
ac26ca64 784 directly, but I'm sick of this for now.
07bf635f
RS
785 */
786 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
787 {
788 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
789 XtVaSetValues (wmshell, XtNiconic,
790 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
791 }
792
793 return needs_a_refresh;
794}
795
796static XtGeometryResult
ebd15611 797EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
07bf635f
RS
798{
799 EmacsFrame ew = (EmacsFrame)widget;
800
801 int mask = request->request_mode;
802 Dimension ok_width, ok_height;
803
804 if (mask & (CWWidth | CWHeight))
805 {
806 round_size_to_char (ew,
807 (mask & CWWidth) ? request->width : ew->core.width,
808 ((mask & CWHeight) ? request->height
809 : ew->core.height),
810 &ok_width, &ok_height);
811 if ((mask & CWWidth) && (ok_width != request->width))
812 {
813 result->request_mode |= CWWidth;
814 result->width = ok_width;
815 }
816 if ((mask & CWHeight) && (ok_height != request->height))
817 {
818 result->request_mode |= CWHeight;
819 result->height = ok_height;
820 }
821 }
822 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
823}
824
07bf635f
RS
825/* Special entrypoints */
826void
ebd15611 827EmacsFrameSetCharSize (Widget widget, int columns, int rows)
07bf635f
RS
828{
829 EmacsFrame ew = (EmacsFrame) widget;
982a94d9 830 struct frame *f = ew->emacs_frame.frame;
177c0ea7 831
5c646d5a 832 x_set_window_size (f, 0, columns, rows);
07bf635f 833}
f403d3c3 834
d793b105 835\f
dfcf069d 836void
ebd15611 837widget_store_internal_border (Widget widget)
d793b105
RS
838{
839 EmacsFrame ew = (EmacsFrame) widget;
840 FRAME_PTR f = ew->emacs_frame.frame;
841
90022f5a 842 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 843}
ab5796a9
MB
844
845/* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
846 (do not change this comment) */