1 /* The emacs frame widget.
2 Copyright (C) 1992-1993, 2000-2016 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or (at
9 your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 /* Emacs 19 face widget ported by Fred Pierresteguy */
21 /* This file has been censored by the Communications Decency Act.
22 That law was passed under the guise of a ban on pornography, but
23 it bans far more than that. This file did not contain pornography,
24 but it was censored nonetheless.
26 For information on US government censorship of the Internet, and
27 what you can do to bring back freedom of the press, see the web
28 site http://www.vtw.org/
40 #include <X11/StringDefs.h>
41 #include <X11/IntrinsicP.h>
42 #include <X11/cursorfont.h>
43 #include "widgetprv.h"
44 #include <X11/ObjectP.h>
45 #include <X11/Shell.h>
46 #include <X11/ShellP.h>
47 #include "../lwlib/lwlib.h"
49 static void EmacsFrameInitialize (Widget request
, Widget
new, ArgList dum1
, Cardinal
*dum2
);
50 static void EmacsFrameDestroy (Widget widget
);
51 static void EmacsFrameRealize (Widget widget
, XtValueMask
*mask
, XSetWindowAttributes
*attrs
);
52 static void EmacsFrameResize (Widget widget
);
53 static XtGeometryResult
EmacsFrameQueryGeometry (Widget widget
, XtWidgetGeometry
*request
, XtWidgetGeometry
*result
);
56 #define offset(field) offsetof (EmacsFrameRec, emacs_frame.field)
58 static XtResource resources
[] = {
59 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof (String
),
60 offset (geometry
), XtRString
, (XtPointer
) 0},
61 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof (Boolean
),
62 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
64 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
65 offset (frame
), XtRImmediate
, 0},
67 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
68 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
69 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
70 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
71 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
72 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
73 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
74 offset (interline
), XtRImmediate
, (XtPointer
)0},
75 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof (Pixel
),
76 offset (foreground_pixel
), XtRString
, "XtDefaultForeground"},
77 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof (Pixel
),
78 offset (cursor_color
), XtRString
, "XtDefaultForeground"},
79 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
80 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
81 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
82 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
83 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
84 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
91 emacsFrameActionsTable [] = {
92 {"keypress", key_press},
93 {"focus_in", emacs_frame_focus_handler},
94 {"focus_out", emacs_frame_focus_handler},
98 emacsFrameTranslations [] = "\
99 <KeyPress>: keypress()\n\
100 <FocusIn>: focus_in()\n\
101 <FocusOut>: focus_out()\n\
105 static EmacsFrameClassRec emacsFrameClassRec
= {
107 /* superclass */ &widgetClassRec
,
108 /* class_name */ "EmacsFrame",
109 /* widget_size */ sizeof (EmacsFrameRec
),
110 /* class_initialize */ 0,
111 /* class_part_initialize */ 0,
112 /* class_inited */ FALSE
,
113 /* initialize */ EmacsFrameInitialize
,
114 /* initialize_hook */ 0,
115 /* realize */ EmacsFrameRealize
,
116 /* actions */ 0, /*emacsFrameActionsTable*/
117 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
118 /* resources */ resources
,
119 /* resource_count */ XtNumber (resources
),
120 /* xrm_class */ NULLQUARK
,
121 /* compress_motion */ TRUE
,
122 /* compress_exposure */ TRUE
,
123 /* compress_enterleave */ TRUE
,
124 /* visible_interest */ FALSE
,
125 /* destroy */ EmacsFrameDestroy
,
126 /* resize */ EmacsFrameResize
,
127 /* expose */ XtInheritExpose
,
129 /* Emacs never does XtSetvalues on this widget, so we have no code
131 /* set_values */ 0, /* Not supported */
132 /* set_values_hook */ 0,
133 /* set_values_almost */ XtInheritSetValuesAlmost
,
134 /* get_values_hook */ 0,
135 /* accept_focus */ XtInheritAcceptFocus
,
136 /* version */ XtVersion
,
137 /* callback_private */ 0,
138 /* tm_table */ 0, /*emacsFrameTranslations*/
139 /* query_geometry */ EmacsFrameQueryGeometry
,
140 /* display_accelerator */ XtInheritDisplayAccelerator
,
145 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
148 get_default_char_pixel_size (EmacsFrame ew
, int *pixel_width
, int *pixel_height
)
150 struct frame
* f
= ew
->emacs_frame
.frame
;
151 *pixel_width
= FRAME_COLUMN_WIDTH (f
);
152 *pixel_height
= FRAME_LINE_HEIGHT (f
);
156 pixel_to_char_size (EmacsFrame ew
, Dimension pixel_width
, Dimension pixel_height
, int *char_width
, int *char_height
)
158 struct frame
* f
= ew
->emacs_frame
.frame
;
159 *char_width
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, (int) pixel_width
);
160 *char_height
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, (int) pixel_height
);
164 pixel_to_text_size (EmacsFrame ew
, Dimension pixel_width
, Dimension pixel_height
, int *text_width
, int *text_height
)
166 struct frame
* f
= ew
->emacs_frame
.frame
;
167 *text_width
= FRAME_PIXEL_TO_TEXT_WIDTH (f
, (int) pixel_width
);
168 *text_height
= FRAME_PIXEL_TO_TEXT_HEIGHT (f
, (int) pixel_height
);
172 char_to_pixel_size (EmacsFrame ew
, int char_width
, int char_height
, Dimension
*pixel_width
, Dimension
*pixel_height
)
174 struct frame
* f
= ew
->emacs_frame
.frame
;
175 *pixel_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, char_width
);
176 *pixel_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, char_height
);
180 round_size_to_char (EmacsFrame ew
, Dimension in_width
, Dimension in_height
, Dimension
*out_width
, Dimension
*out_height
)
184 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
185 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
189 get_wm_shell (Widget w
)
193 for (wmshell
= XtParent (w
);
194 wmshell
&& !XtIsWMShell (wmshell
);
195 wmshell
= XtParent (wmshell
));
200 #if 0 /* Currently not used. */
203 mark_shell_size_user_specified (Widget wmshell
)
205 if (! XtIsWMShell (wmshell
)) emacs_abort ();
206 /* This is kind of sleazy, but I can't see how else to tell it to make it
207 mark the WM_SIZE_HINTS size as user specified when appropriate. */
208 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
214 /* Can't have static frame locals because of some broken compilers.
215 Normally, initializing a variable like this doesn't work in emacs,
216 but it's ok in this file because it must come after lastfile (and
217 thus have its data not go into text space) because Xt needs to
218 write to initialized data objects too.
221 static Boolean first_frame_p
= True
;
225 set_frame_size (EmacsFrame ew
)
227 /* The widget hierarchy is
229 argv[0] emacsShell pane Frame-NAME
230 ApplicationShell EmacsShell Paned EmacsFrame
232 We accept geometry specs in this order:
238 Other possibilities for widget hierarchies might be
240 argv[0] frame pane Frame-NAME
241 ApplicationShell EmacsShell Paned EmacsFrame
243 argv[0] Frame-NAME pane Frame-NAME
244 ApplicationShell EmacsShell Paned EmacsFrame
246 argv[0] Frame-NAME pane emacsTextPane
247 ApplicationShell EmacsFrame Paned EmacsTextPane
249 With the current setup, the text-display-area is the part which is
250 an emacs "frame", since that's the only part managed by emacs proper
251 (the menubar and the parent of the menubar and all that sort of thing
252 are managed by lwlib.)
254 The EmacsShell widget is simply a replacement for the Shell widget
255 which is able to deal with using an externally-supplied window instead
256 of always creating its own. It is not actually emacs specific, and
257 should possibly have class "Shell" instead of "EmacsShell" to simplify
262 /* Hairily merged geometry */
263 struct frame
*f
= ew
->emacs_frame
.frame
;
264 int w
= FRAME_COLS (f
);
265 int h
= FRAME_LINES (f
);
266 Widget wmshell
= get_wm_shell ((Widget
) ew
);
267 Dimension pixel_width
, pixel_height
;
268 /* Each Emacs shell is now independent and top-level. */
270 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) emacs_abort ();
272 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
273 ew
->core
.width
= (frame_resize_pixelwise
274 ? FRAME_PIXEL_WIDTH (f
)
276 ew
->core
.height
= (frame_resize_pixelwise
277 ? FRAME_PIXEL_HEIGHT (f
)
280 frame_size_history_add
281 (f
, Qset_frame_size
, FRAME_TEXT_WIDTH (f
), FRAME_TEXT_HEIGHT (f
),
282 list2 (make_number (ew
->core
.width
), make_number (ew
->core
.height
)));
286 update_wm_hints (EmacsFrame ew
)
288 Widget wmshell
= get_wm_shell ((Widget
) ew
);
291 Dimension rounded_width
;
292 Dimension rounded_height
;
297 int min_rows
= 0, min_cols
= 0;
299 /* This happens when the frame is just created. */
300 if (! wmshell
) return;
302 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
303 &char_width
, &char_height
);
304 char_to_pixel_size (ew
, char_width
, char_height
,
305 &rounded_width
, &rounded_height
);
306 get_default_char_pixel_size (ew
, &cw
, &ch
);
308 base_width
= (wmshell
->core
.width
- ew
->core
.width
309 + (rounded_width
- (char_width
* cw
)));
310 base_height
= (wmshell
->core
.height
- ew
->core
.height
311 + (rounded_height
- (char_height
* ch
)));
313 /* This is kind of sleazy, but I can't see how else to tell it to
314 make it mark the WM_SIZE_HINTS size as user specified.
316 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
318 XtVaSetValues (wmshell
,
319 XtNbaseWidth
, (XtArgVal
) base_width
,
320 XtNbaseHeight
, (XtArgVal
) base_height
,
321 XtNwidthInc
, (XtArgVal
) (frame_resize_pixelwise
? 1 : cw
),
322 XtNheightInc
, (XtArgVal
) (frame_resize_pixelwise
? 1 : ch
),
323 XtNminWidth
, (XtArgVal
) (base_width
+ min_cols
* cw
),
324 XtNminHeight
, (XtArgVal
) (base_height
+ min_rows
* ch
),
329 widget_update_wm_size_hints (Widget widget
)
331 EmacsFrame ew
= (EmacsFrame
) widget
;
332 update_wm_hints (ew
);
336 update_various_frame_slots (EmacsFrame ew
)
338 struct frame
*f
= ew
->emacs_frame
.frame
;
340 f
->internal_border_width
= ew
->emacs_frame
.internal_border_width
;
344 update_from_various_frame_slots (EmacsFrame ew
)
346 struct frame
*f
= ew
->emacs_frame
.frame
;
347 struct x_output
*x
= f
->output_data
.x
;
349 ew
->core
.height
= FRAME_PIXEL_HEIGHT (f
) - x
->menubar_height
;
350 ew
->core
.width
= FRAME_PIXEL_WIDTH (f
);
351 ew
->core
.background_pixel
= FRAME_BACKGROUND_PIXEL (f
);
352 ew
->emacs_frame
.internal_border_width
= f
->internal_border_width
;
353 ew
->emacs_frame
.foreground_pixel
= FRAME_FOREGROUND_PIXEL (f
);
354 ew
->emacs_frame
.cursor_color
= x
->cursor_pixel
;
355 ew
->core
.border_pixel
= x
->border_pixel
;
359 EmacsFrameInitialize (Widget request
, Widget
new, ArgList dum1
, Cardinal
*dum2
)
361 EmacsFrame ew
= (EmacsFrame
) new;
363 if (!ew
->emacs_frame
.frame
)
366 "can't create an emacs frame widget without a frame\n");
370 update_from_various_frame_slots (ew
);
375 resize_cb (Widget widget
,
378 Boolean
* continue_to_dispatch
)
380 EmacsFrameResize (widget
);
385 EmacsFrameRealize (Widget widget
, XtValueMask
*mask
, XSetWindowAttributes
*attrs
)
387 EmacsFrame ew
= (EmacsFrame
) widget
;
389 /* This used to contain SubstructureRedirectMask, but this turns out
390 to be a problem with XIM on Solaris, and events from that mask
391 don't seem to be used. Let's check that. */
392 attrs
->event_mask
= (STANDARD_EVENT_SET
394 | SubstructureNotifyMask
);
395 *mask
|= CWEventMask
;
396 XtCreateWindow (widget
, InputOutput
, (Visual
*) CopyFromParent
, *mask
,
398 /* Some ConfigureNotify events does not end up in EmacsFrameResize so
399 make sure we get them all. Seen with xfcwm4 for example. */
400 XtAddRawEventHandler (widget
, StructureNotifyMask
, False
, resize_cb
, NULL
);
401 update_wm_hints (ew
);
405 EmacsFrameDestroy (Widget widget
)
407 /* All GCs are now freed in x_free_frame_resources. */
411 EmacsFrameResize (Widget widget
)
413 EmacsFrame ew
= (EmacsFrame
) widget
;
414 struct frame
*f
= ew
->emacs_frame
.frame
;
417 pixel_to_text_size (ew
, ew
->core
.width
, ew
->core
.height
, &width
, &height
);
419 frame_size_history_add
420 (f
, QEmacsFrameResize
, width
, height
,
421 list5 (make_number (ew
->core
.width
), make_number (ew
->core
.height
),
422 make_number (FRAME_TOP_MARGIN_HEIGHT (f
)),
423 make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (f
)),
424 make_number (2 * FRAME_INTERNAL_BORDER_WIDTH (f
))));
426 change_frame_size (f
, width
, height
, 0, 1, 0, 1);
428 update_wm_hints (ew
);
429 update_various_frame_slots (ew
);
431 cancel_mouse_face (f
);
434 static XtGeometryResult
435 EmacsFrameQueryGeometry (Widget widget
, XtWidgetGeometry
*request
, XtWidgetGeometry
*result
)
437 EmacsFrame ew
= (EmacsFrame
) widget
;
439 int mask
= request
->request_mode
;
440 Dimension ok_width
, ok_height
;
442 if (mask
& (CWWidth
| CWHeight
))
444 if (!frame_resize_pixelwise
)
445 round_size_to_char (ew
,
446 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
447 ((mask
& CWHeight
) ? request
->height
449 &ok_width
, &ok_height
);
450 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
452 result
->request_mode
|= CWWidth
;
453 result
->width
= ok_width
;
455 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
457 result
->request_mode
|= CWHeight
;
458 result
->height
= ok_height
;
461 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
464 /* Special entry points */
466 EmacsFrameSetCharSize (Widget widget
, int columns
, int rows
)
468 EmacsFrame ew
= (EmacsFrame
) widget
;
469 struct frame
*f
= ew
->emacs_frame
.frame
;
471 if (!frame_inhibit_resize (f
, 0, Qfont
)
472 && !frame_inhibit_resize (f
, 1, Qfont
))
473 x_set_window_size (f
, 0, columns
, rows
, 0);
478 widget_store_internal_border (Widget widget
)
480 EmacsFrame ew
= (EmacsFrame
) widget
;
481 struct frame
*f
= ew
->emacs_frame
.frame
;
483 ew
->emacs_frame
.internal_border_width
= f
->internal_border_width
;