Support resizing frames and windows pixelwise.
[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. */
880e6158 415 change_frame_size (f, w, h, 1, 0, 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
880e6158 470 check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0);
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
1ad2277b
RS
506static char setup_frame_cursor_bits[] =
507{
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
512};
513
07bf635f 514static void
ebd15611 515setup_frame_gcs (EmacsFrame ew)
07bf635f
RS
516{
517 XGCValues gc_values;
518 struct frame* s = ew->emacs_frame.frame;
519 Pixmap blank_stipple, blank_tile;
39d14c25
CY
520 unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
521 | GCStipple | GCTile);
522 Lisp_Object font;
523
524 XSETFONT (font, ew->emacs_frame.font);
525 font = Ffont_xlfd_name (font, Qnil);
526 if (STRINGP (font))
527 {
aad3612f 528 XFontStruct *xfont = XLoadQueryFont (FRAME_DISPLAY_INFO (s)->display,
42a5b22f 529 SSDATA (font));
39d14c25
CY
530 if (xfont)
531 {
532 gc_values.font = xfont->fid;
533 valuemask |= GCFont;
534 }
535 }
07bf635f 536
07bf635f
RS
537 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
538 XGetGCValues returns uninitialized data when we query the stipple
539 (instead of None or something sensible) and it makes things hard.
540
541 This should be fixed for real by not querying the GCs but instead having
542 some GC-based cache instead of the current face-based cache which doesn't
543 effectively cache all of the GC settings we need to use.
544 */
545
85e53327
KH
546 blank_stipple
547 = XCreateBitmapFromData (XtDisplay (ew),
548 RootWindowOfScreen (XtScreen (ew)),
549 setup_frame_cursor_bits, 2, 2);
07bf635f
RS
550
551 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
552 never actually get used as a background tile!
553 */
85e53327 554 blank_tile
5e617bc2 555 = XCreatePixmapFromBitmapData (XtDisplay (ew),
85e53327
KH
556 RootWindowOfScreen (XtScreen (ew)),
557 setup_frame_cursor_bits, 2, 2,
578c21e6 558 0, 1, ew->core.depth);
07bf635f
RS
559
560 /* Normal video */
07bf635f
RS
561 gc_values.foreground = ew->emacs_frame.foreground_pixel;
562 gc_values.background = ew->core.background_pixel;
563 gc_values.graphics_exposures = False;
564 gc_values.stipple = blank_stipple;
565 gc_values.tile = blank_tile;
54e9e953 566 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
39d14c25 567 valuemask, &gc_values);
07bf635f
RS
568
569 /* Reverse video style. */
07bf635f
RS
570 gc_values.foreground = ew->core.background_pixel;
571 gc_values.background = ew->emacs_frame.foreground_pixel;
572 gc_values.graphics_exposures = False;
573 gc_values.stipple = blank_stipple;
574 gc_values.tile = blank_tile;
54e9e953 575 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
39d14c25 576 valuemask, &gc_values);
07bf635f
RS
577
578 /* Cursor has to have an empty stipple. */
07bf635f
RS
579 gc_values.foreground = ew->core.background_pixel;
580 gc_values.background = ew->emacs_frame.cursor_color;
581 gc_values.graphics_exposures = False;
582 gc_values.tile = blank_tile;
85e53327
KH
583 gc_values.stipple
584 = XCreateBitmapFromData (XtDisplay (ew),
585 RootWindowOfScreen (XtScreen (ew)),
586 setup_frame_cursor_bits, 16, 16);
54e9e953 587 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
39d14c25 588 valuemask, &gc_values);
07bf635f
RS
589}
590
591static void
ebd15611 592update_various_frame_slots (EmacsFrame ew)
07bf635f 593{
90022f5a
KS
594 struct frame *f = ew->emacs_frame.frame;
595 struct x_output *x = f->output_data.x;
596 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
597 FRAME_PIXEL_WIDTH (f) = ew->core.width;
598 f->internal_border_width = ew->emacs_frame.internal_border_width;
07bf635f
RS
599
600}
601
602static void
ebd15611 603update_from_various_frame_slots (EmacsFrame ew)
07bf635f 604{
90022f5a
KS
605 struct frame *f = ew->emacs_frame.frame;
606 struct x_output *x = f->output_data.x;
607 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
608 ew->core.width = FRAME_PIXEL_WIDTH (f);
ce593f6e 609 ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
90022f5a 610 ew->emacs_frame.internal_border_width = f->internal_border_width;
07bf635f 611 ew->emacs_frame.font = x->font;
ce593f6e 612 ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
07bf635f
RS
613 ew->emacs_frame.cursor_color = x->cursor_pixel;
614 ew->core.border_pixel = x->border_pixel;
615}
616
177c0ea7 617static void
ebd15611 618EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
07bf635f
RS
619{
620 EmacsFrame ew = (EmacsFrame)new;
621
622 if (!ew->emacs_frame.frame)
623 {
624 fprintf (stderr,
625 "can't create an emacs frame widget without a frame\n");
626 exit (1);
627 }
628
07bf635f 629 update_from_various_frame_slots (ew);
177c0ea7 630 set_frame_size (ew);
07bf635f
RS
631}
632
ad10696b
JD
633static void
634resize_cb (Widget widget,
635 XtPointer closure,
636 XEvent* event,
637 Boolean* continue_to_dispatch)
638{
ad10696b
JD
639 EmacsFrameResize (widget);
640}
641
07bf635f
RS
642
643static void
ebd15611 644EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
07bf635f
RS
645{
646 EmacsFrame ew = (EmacsFrame)widget;
647
486a103d
GM
648 /* This used to contain SubstructureRedirectMask, but this turns out
649 to be a problem with XIM on Solaris, and events from that mask
2fce2bb4 650 don't seem to be used. Let's check that. */
486a103d
GM
651 attrs->event_mask = (STANDARD_EVENT_SET
652 | PropertyChangeMask
653 | SubstructureNotifyMask);
07bf635f
RS
654 *mask |= CWEventMask;
655 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
656 attrs);
ad10696b
JD
657 /* Some ConfigureNotify events does not end up in EmacsFrameResize so
658 make sure we get them all. Seen with xfcwm4 for example. */
659 XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL);
177c0ea7 660 update_wm_hints (ew);
07bf635f
RS
661}
662
07bf635f 663static void
ebd15611 664EmacsFrameDestroy (Widget widget)
07bf635f 665{
4b5c9326 666 /* All GCs are now freed in x_free_frame_resources. */
07bf635f
RS
667}
668
4475bec4 669static void
ebd15611 670EmacsFrameResize (Widget widget)
07bf635f
RS
671{
672 EmacsFrame ew = (EmacsFrame)widget;
673 struct frame *f = ew->emacs_frame.frame;
ad10696b 674 struct x_output *x = f->output_data.x;
07bf635f
RS
675 int columns;
676 int rows;
677
678 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
ad10696b
JD
679 if (columns != FRAME_COLS (f)
680 || rows != FRAME_LINES (f)
681 || ew->core.width != FRAME_PIXEL_WIDTH (f)
682 || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
683 {
880e6158 684 change_frame_size (f, columns, rows, 0, 1, 0, 0);
ad10696b
JD
685 update_wm_hints (ew);
686 update_various_frame_slots (ew);
49feb47d 687
ad10696b
JD
688 cancel_mouse_face (f);
689 }
07bf635f
RS
690}
691
692static Boolean
ebd15611 693EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
07bf635f
RS
694{
695 EmacsFrame cur = (EmacsFrame)cur_widget;
696 EmacsFrame new = (EmacsFrame)new_widget;
697
698 Boolean needs_a_refresh = False;
699 Boolean has_to_recompute_size;
700 Boolean has_to_recompute_gcs;
701 Boolean has_to_update_hints;
702
703 int char_width, char_height;
704 Dimension pixel_width;
705 Dimension pixel_height;
177c0ea7 706
5c646d5a 707 /* AFAIK, this function is never called. -- Jan D, Oct 2009. */
07bf635f
RS
708 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
709 || (cur->emacs_frame.foreground_pixel
710 != new->emacs_frame.foreground_pixel)
711 || (cur->core.background_pixel
712 != new->core.background_pixel)
713 );
177c0ea7 714
07bf635f
RS
715 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
716 && cur->core.width == new->core.width
717 && cur->core.height == new->core.height);
718
719 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
720
721 if (has_to_recompute_gcs)
722 {
723 setup_frame_gcs (new);
724 needs_a_refresh = True;
725 }
177c0ea7 726
07bf635f
RS
727 if (has_to_recompute_size)
728 {
729 pixel_width = new->core.width;
730 pixel_height = new->core.height;
731 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
732 &char_height);
733 char_to_pixel_size (new, char_width, char_height, &pixel_width,
734 &pixel_height);
735 new->core.width = pixel_width;
736 new->core.height = pixel_height;
737
880e6158
MR
738 change_frame_size (new->emacs_frame.frame, char_width, char_height,
739 1, 0, 0, 0);
07bf635f
RS
740 needs_a_refresh = True;
741 }
742
743 if (has_to_update_hints)
744 update_wm_hints (new);
745
746 update_various_frame_slots (new);
747
748 /* #### This doesn't work, I haven't been able to find ANY kludge that
749 will let (x-create-frame '((iconic . t))) work. It seems that changes
750 to wm_shell's iconic slot have no effect after it has been realized,
2dd5c7f7 751 and calling XIconifyWindow doesn't work either (even though the window
07bf635f 752 has been created.) Perhaps there is some property we could smash
ac26ca64 753 directly, but I'm sick of this for now.
07bf635f
RS
754 */
755 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
756 {
757 Widget wmshell = get_wm_shell ((Widget) cur);
cbec8c51
GM
758 XtVaSetValues (wmshell, XtNiconic,
759 (XtArgVal) new->emacs_frame.iconic, NULL);
07bf635f
RS
760 }
761
762 return needs_a_refresh;
763}
764
765static XtGeometryResult
ebd15611 766EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
07bf635f
RS
767{
768 EmacsFrame ew = (EmacsFrame)widget;
769
770 int mask = request->request_mode;
771 Dimension ok_width, ok_height;
772
773 if (mask & (CWWidth | CWHeight))
774 {
775 round_size_to_char (ew,
776 (mask & CWWidth) ? request->width : ew->core.width,
777 ((mask & CWHeight) ? request->height
778 : ew->core.height),
779 &ok_width, &ok_height);
780 if ((mask & CWWidth) && (ok_width != request->width))
781 {
782 result->request_mode |= CWWidth;
783 result->width = ok_width;
784 }
785 if ((mask & CWHeight) && (ok_height != request->height))
786 {
787 result->request_mode |= CWHeight;
788 result->height = ok_height;
789 }
790 }
791 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
792}
793
e4769531 794/* Special entry points */
07bf635f 795void
ebd15611 796EmacsFrameSetCharSize (Widget widget, int columns, int rows)
07bf635f
RS
797{
798 EmacsFrame ew = (EmacsFrame) widget;
982a94d9 799 struct frame *f = ew->emacs_frame.frame;
177c0ea7 800
880e6158 801 x_set_window_size (f, 0, columns, rows, 0);
07bf635f 802}
f403d3c3 803
d793b105 804\f
dfcf069d 805void
ebd15611 806widget_store_internal_border (Widget widget)
d793b105
RS
807{
808 EmacsFrame ew = (EmacsFrame) widget;
a10c8269 809 struct frame *f = ew->emacs_frame.frame;
d793b105 810
90022f5a 811 ew->emacs_frame.internal_border_width = f->internal_border_width;
d793b105 812}