1 /* Functions for the X window system.
2 Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not synched with FSF. */
24 /* Substantially rewritten for XEmacs. */
29 #include "console-x.h"
30 #include "xintrinsicp.h" /* CoreP.h needs this */
31 #include <X11/CoreP.h> /* Numerous places access the fields of
32 a core widget directly. We could
33 use XtGetValues(), but ... */
34 #include <X11/Shell.h>
35 #include <X11/ShellP.h>
37 #include "EmacsManager.h"
38 #include "EmacsFrameP.h"
39 #include "EmacsShell.h"
40 #ifdef EXTERNAL_WIDGET
41 #include "ExternalShell.h"
44 #include "objects-x.h"
45 #include "scrollbar-x.h"
61 #if defined (HAVE_OFFIX_DND) || defined (HAVE_CDE)
62 #include "events-mod.h"
65 /* Default properties to use when creating frames. */
66 Lisp_Object Vdefault_x_frame_plist;
68 Lisp_Object Qwindow_id;
69 Lisp_Object Qx_resource_name;
71 EXFUN (Fx_window_id, 1);
74 /************************************************************************/
75 /* helper functions */
76 /************************************************************************/
78 /* Return the Emacs frame-object corresponding to an X window */
80 x_window_to_frame (struct device *d, Window wdesc)
82 Lisp_Object tail, frame;
85 /* This function was previously written to accept only a window argument
86 (and to loop over all devices looking for a matching window), but
87 that is incorrect because window ID's are not unique across displays. */
89 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
95 if (FRAME_X_P (f) && XtWindow (FRAME_X_TEXT_WIDGET (f)) == wdesc)
101 /* Like x_window_to_frame but also compares the window with the widget's
104 x_any_window_to_frame (struct device *d, Window wdesc)
106 Lisp_Object tail, frame;
109 assert (DEVICE_X_P (d));
111 /* This function was previously written to accept only a window argument
112 (and to loop over all devices looking for a matching window), but
113 that is incorrect because window ID's are not unique across displays. */
115 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
121 /* This frame matches if the window is any of its widgets. */
122 if (wdesc == XtWindow (FRAME_X_SHELL_WIDGET (f)) ||
123 wdesc == XtWindow (FRAME_X_CONTAINER_WIDGET (f)) ||
124 wdesc == XtWindow (FRAME_X_TEXT_WIDGET (f)))
127 /* Match if the window is one of the widgets at the top of the frame
128 (menubar, Energize psheets). */
130 /* Note: Jamie once said
132 "Do *not* match if the window is this frame's psheet."
134 But this is wrong and will screw up some functions that expect
135 x_any_window_to_frame() to work as advertised. I think the reason
136 for this statement is that, in the old (broken) event loop, where
137 not all events went through XtDispatchEvent(), psheet events
138 would incorrectly get sucked away by Emacs if this function matched
139 on psheet widgets. */
141 for (i = 0; i < FRAME_X_NUM_TOP_WIDGETS (f); i++)
143 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
144 if (wid && XtIsManaged (wid) && wdesc == XtWindow (wid))
148 #ifdef HAVE_SCROLLBARS
149 /* Match if the window is one of this frame's scrollbars. */
150 if (x_window_is_scrollbar (f, wdesc))
159 x_any_widget_or_parent_to_frame (struct device *d, Widget widget)
163 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
166 widget = XtParent (widget);
173 decode_x_frame (Lisp_Object frame)
176 XSETFRAME (frame, selected_frame ());
177 CHECK_LIVE_FRAME (frame);
178 /* this will also catch dead frames, but putting in the above check
179 results in a more useful error */
180 CHECK_X_FRAME (frame);
181 return XFRAME (frame);
185 /************************************************************************/
186 /* window-manager interactions */
187 /************************************************************************/
190 /* Not currently used. */
193 x_wm_mark_shell_size_user_specified (Widget wmshell)
195 if (! XtIsWMShell (wmshell)) abort ();
196 EmacsShellSetSizeUserSpecified (wmshell);
200 x_wm_mark_shell_position_user_specified (Widget wmshell)
202 if (! XtIsWMShell (wmshell)) abort ();
203 EmacsShellSetPositionUserSpecified (wmshell);
209 x_wm_set_shell_iconic_p (Widget shell, int iconic_p)
211 if (! XtIsWMShell (shell)) abort ();
213 /* Because of questionable logic in Shell.c, this sequence can't work:
215 w = XtCreatePopupShell (...);
216 Xt_SET_VALUE (w, XtNiconic, True);
219 The iconic resource is only consulted at initialization time (when
220 XtCreatePopupShell is called) instead of at realization time (just
221 before the window gets created, which would be more sensible) or
222 at management-time (just before the window gets mapped, which would
223 be most sensible of all).
225 The bug is that Shell's SetValues method doesn't do anything to
226 w->wm.wm_hints.initial_state until after the widget has been realized.
227 Calls to XtSetValues are ignored in the window between creation and
228 realization. This is true of MIT X11R5 patch level 25, at least.
229 (Apparently some other versions of Xt don't have this bug?)
231 Xt_SET_VALUE (shell, XtNiconic, iconic_p);
232 EmacsShellSmashIconicHint (shell, iconic_p);
236 x_wm_set_cell_size (Widget wmshell, int cw, int ch)
240 if (!XtIsWMShell (wmshell))
242 if (cw <= 0 || ch <= 0)
245 XtSetArg (al [0], XtNwidthInc, cw);
246 XtSetArg (al [1], XtNheightInc, ch);
247 XtSetValues (wmshell, al, 2);
251 x_wm_set_variable_size (Widget wmshell, int width, int height)
255 if (!XtIsWMShell (wmshell))
257 #ifdef DEBUG_GEOMETRY_MANAGEMENT
258 /* See comment in EmacsShell.c */
259 printf ("x_wm_set_variable_size: %d %d\n", width, height);
263 XtSetArg (al [0], XtNwidthCells, width);
264 XtSetArg (al [1], XtNheightCells, height);
265 XtSetValues (wmshell, al, 2);
268 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS
269 and WM_DELETE_WINDOW, then add them. (They may already be present
270 because of the toolkit (Motif adds them, for example, but Xt doesn't).
273 x_wm_hack_wm_protocols (Widget widget)
275 Display *dpy = XtDisplay (widget);
276 struct device *d = get_device_from_display (dpy);
277 Window w = XtWindow (widget);
281 if (!XtIsWMShell (widget))
285 Atom type, *atoms = 0;
287 unsigned long nitems = 0;
288 unsigned long bytes_after;
290 if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d),
291 0, 100, False, XA_ATOM,
292 &type, &format, &nitems, &bytes_after,
293 (unsigned char **) &atoms)
294 && format == 32 && type == XA_ATOM)
298 if (atoms [nitems] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
300 else if (atoms [nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
303 if (atoms) XFree ((char *) atoms);
308 if (need_delete) props[count++] = DEVICE_XATOM_WM_DELETE_WINDOW (d);
309 if (need_focus) props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d);
311 XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32,
312 PropModeAppend, (unsigned char *) props, count);
317 x_wm_store_class_hints (Widget shell, char *frame_name)
319 Display *dpy = XtDisplay (shell);
320 char *app_name, *app_class;
321 XClassHint classhint;
323 if (!XtIsWMShell (shell))
326 XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
327 classhint.res_name = frame_name;
328 classhint.res_class = app_class;
329 XSetClassHint (dpy, XtWindow (shell), &classhint);
334 x_wm_maybe_store_wm_command (struct frame *f)
336 Widget w = FRAME_X_SHELL_WIDGET (f);
337 struct device *d = XDEVICE (FRAME_DEVICE (f));
339 if (!XtIsWMShell (w))
342 if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
346 make_argc_argv (Vcommand_line_args, &argc, &argv);
347 XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
348 free_argc_argv (argv);
349 XSETFRAME (DEVICE_X_WM_COMMAND_FRAME (d), f);
353 /* If we're deleting the frame on which the WM_COMMAND property has been
354 set, then move that property to another frame so that there is exactly
355 one frame that has that property set.
358 x_wm_maybe_move_wm_command (struct frame *f)
360 struct device *d = XDEVICE (FRAME_DEVICE (f));
362 /* There may not be a frame in DEVICE_X_WM_COMMAND_FRAME()
363 if we C-c'ed at startup at the right time. */
364 if (FRAMEP (DEVICE_X_WM_COMMAND_FRAME (d))
365 && f == XFRAME (DEVICE_X_WM_COMMAND_FRAME (d)))
367 Lisp_Object rest = DEVICE_FRAME_LIST (d);
368 DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
369 /* find some random other X frame that is not this one, or give up */
370 /* skip non-top-level (ExternalClient) frames */
371 while (!NILP (rest) &&
372 (f == XFRAME (XCAR (rest)) ||
373 !FRAME_X_TOP_LEVEL_FRAME_P (XFRAME (XCAR (rest)))))
377 f = XFRAME (XCAR (rest));
379 x_wm_maybe_store_wm_command (f);
383 #endif /* !HAVE_SESSION */
386 x_frame_iconified_p (struct frame *f)
390 unsigned long nitems, bytesafter;
391 unsigned long *datap = 0;
394 struct device *d = XDEVICE (FRAME_DEVICE (f));
396 widget = FRAME_X_SHELL_WIDGET (f);
397 if (Success == XGetWindowProperty (XtDisplay (widget), XtWindow (widget),
398 DEVICE_XATOM_WM_STATE (d), 0, 2, False,
399 DEVICE_XATOM_WM_STATE (d), &actual_type,
400 &actual_format, &nitems, &bytesafter,
401 (unsigned char **) &datap)
404 if (nitems <= 2 /* "suggested" by ICCCM version 1 */
405 && datap[0] == IconicState)
407 XFree ((char *) datap);
413 /************************************************************************/
414 /* frame properties */
415 /************************************************************************/
417 /* Connect the frame-property names (symbols) to the corresponding
418 X Resource Manager names. The name of a property, as a Lisp symbol,
419 has an `x-resource-name' property which is a Lisp_String. */
422 init_x_prop_symbols (void)
424 #define def(sym, rsrc) \
425 pure_put (sym, Qx_resource_name, build_string (rsrc))
426 #define defi(sym,rsrc) \
427 def (sym, rsrc); pure_put (sym, Qintegerp, Qt)
429 #if 0 /* this interferes with things. #### fix this right */
430 def (Qminibuffer, XtNminibuffer);
431 def (Qunsplittable, XtNunsplittable);
433 defi(Qinternal_border_width, XtNinternalBorderWidth);
435 def (Qtop_toolbar_shadow_color, XtNtopToolBarShadowColor);
436 def (Qbottom_toolbar_shadow_color, XtNbottomToolBarShadowColor);
437 def (Qbackground_toolbar_color, XtNbackgroundToolBarColor);
438 def (Qtop_toolbar_shadow_pixmap, XtNtopToolBarShadowPixmap);
439 def (Qbottom_toolbar_shadow_pixmap, XtNbottomToolBarShadowPixmap);
440 defi(Qtoolbar_shadow_thickness, XtNtoolBarShadowThickness);
442 def (Qscrollbar_placement, XtNscrollBarPlacement);
443 defi(Qinter_line_space, XtNinterline);
444 /* font, foreground */
445 def (Qiconic, XtNiconic);
446 def (Qbar_cursor, XtNbarCursor);
447 def (Qvisual_bell, XtNvisualBell);
448 defi(Qbell_volume, XtNbellVolume);
449 def (Qpointer_background, XtNpointerBackground);
450 def (Qpointer_color, XtNpointerColor);
451 def (Qtext_pointer, XtNtextPointer);
452 def (Qspace_pointer, XtNspacePointer);
453 def (Qmodeline_pointer, XtNmodeLinePointer);
454 def (Qgc_pointer, XtNgcPointer);
455 /* geometry, initial_geometry */
456 def (Qinitially_unmapped, XtNinitiallyUnmapped);
457 /* preferred_width, preferred_height */
458 def (Quse_backing_store, XtNuseBackingStore);
462 def (Qborder_color, XtNborderColor);
463 defi(Qborder_width, XtNborderWidth);
464 defi(Qwidth, XtNwidth);
465 defi(Qheight, XtNheight);
473 color_to_string (Widget w, unsigned long pixel)
479 XQueryColor (XtDisplay (w), w->core.colormap, &color);
480 sprintf (buf, "#%04x%04x%04x", color.red, color.green, color.blue);
481 return build_string (buf);
485 x_get_top_level_position (Display *d, Window w, Position *x, Position *y)
487 Window root, parent = w, *children;
488 unsigned int nchildren;
489 XWindowAttributes xwa;
494 if (!XQueryTree (d, w, &root, &parent, &children, &nchildren))
502 while (root != parent);
503 XGetWindowAttributes (d, w, &xwa);
510 x_smash_bastardly_shell_position (Widget shell)
512 /* Naturally those bastards who wrote Xt couldn't be bothered
513 to learn about race conditions and such. We can't trust
514 the X and Y values to have any semblance of correctness,
515 so we smash the right values in place. */
517 /* We might be called before we've actually realized the window (if
518 we're checking for the minibuffer resource). This will bomb in
519 that case so we don't bother calling it. */
520 if (XtWindow (shell))
521 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
522 &shell->core.x, &shell->core.y);
527 x_frame_property (struct frame *f, Lisp_Object property)
529 Widget shell = FRAME_X_SHELL_WIDGET (f);
530 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
531 Widget gw = (Widget) w;
533 if (EQ (Qleft, property) || EQ (Qtop, property))
536 if (!XtWindow(shell))
538 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
539 if (EQ (Qleft, property)) return make_int (x);
540 if (EQ (Qtop, property)) return make_int (y);
542 if (EQ (Qborder_width, property))
543 return make_int (w->core.border_width);
544 if (EQ (Qinternal_border_width, property))
545 return make_int (w->emacs_frame.internal_border_width);
546 if (EQ (Qborder_color, property))
547 return color_to_string (gw, w->core.border_pixel);
549 if (EQ (Qtop_toolbar_shadow_color, property))
550 return color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel);
551 if (EQ (Qbottom_toolbar_shadow_color, property))
552 return color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel);
553 if (EQ (Qbackground_toolbar_color, property))
554 return color_to_string (gw, w->emacs_frame.background_toolbar_pixel);
555 if (EQ (Qtoolbar_shadow_thickness, property))
556 return make_int (w->emacs_frame.toolbar_shadow_thickness);
557 #endif /* HAVE_TOOLBARS */
558 if (EQ (Qinter_line_space, property))
559 return make_int (w->emacs_frame.interline);
560 if (EQ (Qwindow_id, property))
561 return Fx_window_id (make_frame (f));
567 x_internal_frame_property_p (struct frame *f, Lisp_Object property)
569 return EQ (property, Qleft)
570 || EQ (property, Qtop)
571 || EQ (property, Qborder_width)
572 || EQ (property, Qinternal_border_width)
573 || EQ (property, Qborder_color)
575 || EQ (property, Qtop_toolbar_shadow_color)
576 || EQ (property, Qbottom_toolbar_shadow_color)
577 || EQ (property, Qbackground_toolbar_color)
578 || EQ (property, Qtoolbar_shadow_thickness)
579 #endif /* HAVE_TOOLBARS */
580 || EQ (property, Qinter_line_space)
581 || EQ (property, Qwindow_id)
582 || STRINGP (property);
586 x_frame_properties (struct frame *f)
588 Lisp_Object props = Qnil;
589 Widget shell = FRAME_X_SHELL_WIDGET (f);
590 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
591 Widget gw = (Widget) w;
594 props = cons3 (Qwindow_id, Fx_window_id (make_frame (f)), props);
595 props = cons3 (Qinter_line_space, make_int (w->emacs_frame.interline), props);
598 props = cons3 (Qtoolbar_shadow_thickness,
599 make_int (w->emacs_frame.toolbar_shadow_thickness),
601 props = cons3 (Qbackground_toolbar_color,
602 color_to_string (gw, w->emacs_frame.background_toolbar_pixel),
604 props = cons3 (Qbottom_toolbar_shadow_color,
605 color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel),
607 props = cons3 (Qtop_toolbar_shadow_color,
608 color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel),
610 #endif /* HAVE_TOOLBARS */
612 props = cons3 (Qborder_color,
613 color_to_string (gw, w->core.border_pixel), props);
614 props = cons3 (Qinternal_border_width,
615 make_int (w->emacs_frame.internal_border_width), props);
616 props = cons3 (Qborder_width, make_int (w->core.border_width), props);
618 if (!XtWindow(shell))
621 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
623 props = cons3 (Qtop, make_int (y), props);
624 props = cons3 (Qleft, make_int (x), props);
630 /* Functions called only from `x_set_frame_properties' to set
631 individual properties. */
634 x_set_frame_text_value (struct frame *f, Bufbyte *value,
635 String Xt_resource_name,
636 String Xt_resource_encoding_name)
638 Atom encoding = XA_STRING;
639 String new_XtValue = (String) value;
640 String old_XtValue = NULL;
644 /* Optimize for common ASCII case */
645 for (ptr = value; *ptr; ptr++)
646 if (!BYTE_ASCII_P (*ptr))
649 encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f)));
650 GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA ((CONST char *) value, tmp);
651 new_XtValue = (String) tmp;
656 /* ### Caching is device-independent - belongs in update_frame_title. */
657 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
658 if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
661 XtSetArg (al[0], Xt_resource_name, new_XtValue);
662 XtSetArg (al[1], Xt_resource_encoding_name, encoding);
663 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
668 x_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
670 x_set_frame_text_value (f, name, XtNtitle, XtNtitleEncoding);
674 x_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
676 x_set_frame_text_value (f, name, XtNiconName, XtNiconNameEncoding);
679 /* Set the initial frame size as specified. This function is used
680 when the frame's widgets have not yet been realized. In this
681 case, it is not sufficient just to set the width and height of
682 the EmacsFrame widget, because they will be ignored when the
683 widget is realized (instead, the shell's geometry resource is
687 x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
688 unsigned int w, unsigned int h)
690 char shell_geom [255];
693 char uspos = !!(flags & (XValue | YValue));
694 char ussize = !!(flags & (WidthValue | HeightValue));
697 /* assign the correct size to the EmacsFrame widget ... */
698 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
700 /* and also set the WMShell's geometry */
701 (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
702 (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
705 sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
707 sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
709 sprintf (shell_geom, "=%dx%d", w, h);
713 temp = (char *) xmalloc (1 + strlen (shell_geom));
714 strcpy (temp, shell_geom);
715 FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
720 Xt_SET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp);
723 /* Report to X that a frame property of frame S is being set or changed.
724 If the property is not specially recognized, do nothing.
728 x_set_frame_properties (struct frame *f, Lisp_Object plist)
731 Dimension width = 0, height = 0;
732 Bool width_specified_p = False;
733 Bool height_specified_p = False;
734 Bool x_position_specified_p = False;
735 Bool y_position_specified_p = False;
736 Bool internal_border_width_specified = False;
738 Widget w = FRAME_X_TEXT_WIDGET (f);
740 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
742 Lisp_Object prop = Fcar (tail);
743 Lisp_Object val = Fcar (Fcdr (tail));
749 if (XSTRING_LENGTH (prop) == 0)
752 GET_C_STRING_CTEXT_DATA_ALLOCA (prop, extprop);
755 CONST Extbyte *extval;
758 GET_STRING_CTEXT_DATA_ALLOCA (val, extval, extvallen);
759 XtVaSetValues (w, XtVaTypedArg, extprop,
760 XtRString, extval, extvallen + 1,
764 XtVaSetValues (w, XtVaTypedArg, extprop, XtRInt,
765 XINT (val), sizeof (int),
768 else if (SYMBOLP (prop))
770 Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
771 int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
773 if (NILP (prop) || NILP (str))
775 /* Kludge to handle the font property. */
776 if (EQ (prop, Qfont))
778 /* If the value is not a string we silently ignore it. */
781 Lisp_Object frm, font_spec;
784 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
786 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
787 update_frame_face_values (f);
797 /* Kludge the width/height so that we interpret them in characters
798 instead of pixels. Yuck yuck yuck. */
799 if (!strcmp ((char *) XSTRING_DATA (str), "width"))
803 width_specified_p = True;
806 if (!strcmp ((char *) XSTRING_DATA (str), "height"))
810 height_specified_p = True;
813 /* Further kludge the x/y. */
814 if (!strcmp ((char *) XSTRING_DATA (str), "x"))
817 x = (Position) XINT (val);
818 x_position_specified_p = True;
821 if (!strcmp ((char *) XSTRING_DATA (str), "y"))
824 y = (Position) XINT (val);
825 y_position_specified_p = True;
828 /* Have you figured out by now that this entire function is
829 one gigantic kludge? */
830 if (!strcmp ((char *) XSTRING_DATA (str),
831 "internalBorderWidth"))
833 internal_border_width_specified = True;
839 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val));
841 else if (EQ (val, Qt))
843 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/
845 else if (EQ (val, Qnil))
847 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/
852 XtVaSetValues (w, XtVaTypedArg,
854 (char *) XSTRING_DATA (str),
857 XSTRING_LENGTH (val) + 1,
861 #ifdef HAVE_SCROLLBARS
862 if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth")
863 || !strcmp ((char *) XSTRING_DATA (str),
866 x_update_frame_scrollbars (f);
868 #endif /* HAVE_SCROLLBARS */
872 /* Kludge kludge kludge. We need to deal with the size and position
875 int size_specified_p = width_specified_p || height_specified_p;
876 int position_specified_p = x_position_specified_p ||
877 y_position_specified_p;
879 if (!width_specified_p)
880 width = FRAME_WIDTH (f);
881 if (!height_specified_p)
882 height = FRAME_HEIGHT (f);
884 /* Kludge kludge kludge kludge. */
885 if (position_specified_p &&
886 (!x_position_specified_p || !y_position_specified_p))
889 Widget shell = FRAME_X_SHELL_WIDGET (f);
890 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
891 (x_position_specified_p ? &dummy : &x),
892 (y_position_specified_p ? &dummy : &y));
894 x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
895 y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
899 if (!f->init_finished)
901 int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
902 (position_specified_p ?
903 XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
906 || position_specified_p
907 || internal_border_width_specified)
908 x_set_initial_frame_size (f, flags, x, y, width, height);
912 if (size_specified_p || internal_border_width_specified)
915 XSETFRAME (frame, f);
916 Fset_frame_size (frame, make_int (width),
917 make_int (height), Qnil);
919 if (position_specified_p)
922 XSETFRAME (frame, f);
923 Fset_frame_position (frame, make_int (x), make_int (y));
929 static int frame_title_format_already_set;
932 maybe_set_frame_title_format (Widget shell)
935 /* Only do this if this is the first X frame we're creating.
937 If the *title resource (or -title option) was specified, then
938 set frame-title-format to its value.
941 if (!frame_title_format_already_set)
943 /* No doubt there's a less stupid way to do this. */
945 XtResource resources [2];
946 results [0] = results [1] = 0;
947 resources [0].resource_name = XtNtitle;
948 resources [0].resource_class = XtCTitle;
949 resources [0].resource_type = XtRString;
950 resources [0].resource_size = sizeof (String);
951 resources [0].resource_offset = 0;
952 resources [0].default_type = XtRString;
953 resources [0].default_addr = 0;
954 resources [1].resource_name = XtNiconName;
955 resources [1].resource_class = XtCIconName;
956 resources [1].resource_type = XtRString;
957 resources [1].resource_size = sizeof (String);
958 resources [1].resource_offset = sizeof (char *);
959 resources [1].default_type = XtRString;
960 resources [1].default_addr = 0;
961 XtGetSubresources (XtParent (shell), (XtPointer) results,
963 shell->core.widget_class->core_class.class_name,
964 resources, XtNumber (resources), 0, 0);
966 Vframe_title_format = build_string (results[0]);
968 Vframe_icon_title_format = build_string (results[1]);
971 frame_title_format_already_set = 1;
978 static Widget CurrentDragWidget = NULL;
979 static XtCallbackRec dnd_convert_cb_rec[2];
980 static XtCallbackRec dnd_destroy_cb_rec[2];
981 static int drag_not_done = 0;
984 x_cde_destroy_callback (Widget widget, XtPointer clientData,
987 DtDndDragFinishCallbackStruct *dragFinishInfo =
988 (DtDndDragFinishCallbackStruct *)callData;
989 DtDndContext *dragData = dragFinishInfo->dragData;
993 if (callData != NULL && dragData != NULL)
995 if (dragData->protocol == DtDND_BUFFER_TRANSFER)
997 for (i = 0; i < dragData->numItems; i++)
999 XtFree(dragData->data.buffers[i].bp);
1000 if (dragData->data.buffers[i].name)
1001 XtFree(dragData->data.buffers[i].name);
1006 for (i = 0; i < dragData->numItems; i++)
1007 XtFree(dragData->data.files[i]);
1011 /* free the data string */
1014 CurrentDragWidget = NULL;
1018 x_cde_convert_callback (Widget widget, XtPointer clientData,
1021 DtDndConvertCallbackStruct *convertInfo =
1022 (DtDndConvertCallbackStruct *) callData;
1023 char *textdata = (char *) clientData;
1024 char *textptr = NULL;
1027 if (convertInfo == NULL)
1032 if ((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER
1033 && convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER) ||
1034 (convertInfo->reason != DtCR_DND_CONVERT_DATA))
1039 for (textptr=textdata, i=0;
1040 i<convertInfo->dragData->numItems;
1041 textptr+=strlen(textptr)+1, i++)
1043 if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER)
1045 convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr);
1046 convertInfo->dragData->data.buffers[i].size = strlen(textptr);
1047 convertInfo->dragData->data.buffers[i].name = NULL;
1051 convertInfo->dragData->data.files[i] = XtNewString(textptr);
1055 convertInfo->status = DtDND_SUCCESS;
1059 abort_current_drag(Lisp_Object arg)
1061 if (CurrentDragWidget && drag_not_done)
1063 XmDragCancel(CurrentDragWidget);
1064 CurrentDragWidget = NULL;
1069 DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 3, 3, 0, /*
1070 Start a CDE drag from a buffer.
1071 First argument is the event that started the drag (must be a
1072 button-press-event),
1073 second arg defines if the data should be treated as a buffer or
1074 a filename transfer (set to nil for buffer transfer),
1075 and the third argument is a list of data strings.
1076 WARNING: can only handle plain/text and file: transfers!
1078 (event, dragtype, dragdata))
1082 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1084 Widget wid = FRAME_X_TEXT_WIDGET (f);
1085 Display *display = XtDisplayOfObject (wid);
1086 struct device *d = get_device_from_display (display);
1087 struct x_device *xd = DEVICE_X_DATA (d);
1088 XWindowAttributes win_attrib;
1089 unsigned int modifier = 0, state = 0;
1091 int numItems = 0, textlen = 0, pos = 0;
1092 struct Lisp_Event *lisp_event = XEVENT(event);
1093 Lisp_Object item = Qnil;
1094 struct gcpro gcpro1;
1096 /* only drag if this is really a press */
1097 if (EVENT_TYPE(lisp_event) != button_press_event
1098 || !LISTP(dragdata))
1104 * not so cross hack that converts a emacs event back to a XEvent
1107 x_event.xbutton.type = ButtonPress;
1108 x_event.xbutton.send_event = False;
1109 x_event.xbutton.display = XtDisplayOfObject(wid);
1110 x_event.xbutton.window = XtWindowOfObject(wid);
1111 x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0);
1112 x_event.xbutton.subwindow = 0;
1113 x_event.xbutton.time = lisp_event->timestamp;
1114 x_event.xbutton.x = lisp_event->event.button.x;
1115 x_event.xbutton.y = lisp_event->event.button.y;
1116 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1117 x_event.xbutton.window,
1120 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1121 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1125 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1126 x_event.xbutton.y_root = lisp_event->event.button.y;
1128 modifier = lisp_event->event.button.modifiers;
1129 if (modifier & MOD_SHIFT) state |= ShiftMask;
1130 if (modifier & MOD_CONTROL) state |= ControlMask;
1131 if (modifier & MOD_META) state |= xd->MetaMask;
1132 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1133 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1134 if (modifier & MOD_ALT) state |= xd->AltMask;
1135 state |= Button1Mask << (lisp_event->event.button.button-1);
1137 x_event.xbutton.state = state;
1138 x_event.xbutton.button = lisp_event->event.button.button;
1139 x_event.xkey.same_screen = True;
1141 /* convert data strings into a big string */
1143 while (!NILP (item))
1145 if (!STRINGP (XCAR (item)))
1150 textlen += XSTRING_LENGTH (XCAR (item)) + 1;
1158 * concatenate all strings given to one large string, with
1159 * \0 as separator. List is ended by \0.
1161 Ctext = (char *)xmalloc (textlen+1);
1165 while (!NILP (item))
1167 if (!STRINGP (XCAR (item)))
1174 strcpy (Ctext+pos, (CONST char *)XSTRING_DATA (XCAR (item)));
1175 pos += XSTRING_LENGTH (XCAR (item)) + 1;
1180 dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
1181 dnd_convert_cb_rec[0].closure = (XtPointer) Ctext;
1182 dnd_convert_cb_rec[1].callback = NULL;
1183 dnd_convert_cb_rec[1].closure = NULL;
1185 dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
1186 dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext;
1187 dnd_destroy_cb_rec[1].callback = NULL;
1188 dnd_destroy_cb_rec[1].closure = NULL;
1191 DtDndDragStart (wid, &x_event,
1192 (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER),
1202 return numItems?Qt:Qnil;
1209 x_cde_transfer_callback (Widget widget, XtPointer clientData,
1212 char *filePath, *hurl;
1214 Lisp_Object frame = Qnil;
1215 Lisp_Object l_type = Qnil;
1216 Lisp_Object l_data = Qnil;
1217 DtDndTransferCallbackStruct *transferInfo = NULL;
1218 struct gcpro gcpro1, gcpro2, gcpro3;
1221 this needs to be changed to the new protocol:
1222 - we need the button, modifier and pointer states to create a
1223 correct misc_user_event
1224 - the data must be converted to the new format (URL/MIME)
1228 transferInfo = (DtDndTransferCallbackStruct *) callData;
1229 if (transferInfo == NULL)
1232 GCPRO3 (frame, l_type, l_data);
1234 frame = make_frame ((struct frame *) clientData);
1236 if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
1238 l_type = Qdragdrop_URL;
1240 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1242 filePath = transferInfo->dropData->data.files[ii];
1243 hurl = dnd_url_hexify_string ((char *)filePath, "file:");
1244 /* ### Mule-izing required */
1245 l_data = Fcons (make_string ((Bufbyte* )hurl,
1251 else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
1253 int speccount = specpdl_depth();
1255 /* Problem: all buffers a treated as text/plain!!!
1256 Solution: Also support DtDND_TEXT_TRANSFER
1257 perhaps implementation of the Motif protocol
1258 (which is the base of CDE) will clear this */
1259 l_type = Qdragdrop_MIME;
1260 record_unwind_protect(abort_current_drag, Qnil);
1262 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1264 /* let us forget this name thing for now... */
1265 /* filePath = transferInfo->dropData->data.buffers[ii].name;
1266 path = (filePath == NULL) ? Qnil
1267 : make_string ((Bufbyte *)filePath, strlen (filePath)); */
1268 /* what, if the data is no text, and how can I tell it? */
1269 l_data = Fcons ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1270 make_string ((Bufbyte *)"8bit", 4),
1271 make_string ((Bufbyte *)transferInfo->dropData->data.buffers[ii].bp,
1272 transferInfo->dropData->data.buffers[ii].size) ),
1276 unbind_to(speccount, Qnil);
1278 else /* the other cases: NOOP_TRANSFER */
1281 /* The Problem: no button and mods from CDE... */
1283 enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch,
1284 Fcons (l_type, l_data),
1285 0 /* this is the button */,
1286 0 /* these are the mods */,
1293 #endif /* HAVE_CDE */
1295 #ifdef HAVE_OFFIX_DND
1297 DEFUN ("offix-start-drag-internal", Foffix_start_drag_internal, 2, 3, 0, /*
1298 Start a OffiX drag from a buffer.
1299 First arg is the event that started the drag,
1300 second arg should be some string, and the third
1301 is the type of the data (this should be an int).
1302 The type defaults to DndText (4).
1304 (event, data, dtyp))
1308 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1310 Widget wid = FRAME_X_TEXT_WIDGET (f);
1311 Display *display = XtDisplayOfObject (wid);
1312 struct device *d = get_device_from_display (display);
1313 struct x_device *xd = DEVICE_X_DATA (d);
1314 XWindowAttributes win_attrib;
1315 unsigned int modifier = 0, state = 0;
1316 char *dnd_data = NULL;
1317 unsigned long dnd_len = 0;
1318 int dnd_typ = DndText, dnd_dealloc = 0;
1319 struct Lisp_Event *lisp_event = XEVENT(event);
1321 /* only drag if this is really a press */
1322 if (EVENT_TYPE(lisp_event) != button_press_event)
1325 /* get the desired type */
1326 if (!NILP (dtyp) && INTP (dtyp))
1327 dnd_typ = XINT (dtyp);
1329 if (dnd_typ == DndFiles)
1331 Lisp_Object run = data;
1334 if (NILP ( Flistp (data)))
1337 /* construct the data from a list of files */
1339 dnd_data = (char *) xmalloc (1);
1343 if (!STRINGP (XCAR (run)))
1348 len = XSTRING_LENGTH (XCAR (run)) + 1;
1349 dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
1350 strcpy (dnd_data + dnd_len - 1, (CONST char *)XSTRING_DATA (XCAR (run)));
1355 dnd_data[dnd_len - 1] = 0; /* the list-ending zero */
1361 if (!STRINGP (data))
1364 /* and whats with MULE data ??? */
1365 dnd_data = (char *)XSTRING_DATA (data);
1366 dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */
1371 * not so cross hack that converts a emacs event back to a XEvent
1374 x_event.xbutton.type = ButtonPress;
1375 x_event.xbutton.send_event = False;
1376 x_event.xbutton.display = XtDisplayOfObject(wid);
1377 x_event.xbutton.window = XtWindowOfObject(wid);
1378 x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0);
1379 x_event.xbutton.subwindow = 0;
1380 x_event.xbutton.time = lisp_event->timestamp;
1381 x_event.xbutton.x = lisp_event->event.button.x;
1382 x_event.xbutton.y = lisp_event->event.button.y;
1383 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1384 x_event.xbutton.window,
1387 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1388 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1392 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1393 x_event.xbutton.y_root = lisp_event->event.button.y;
1396 modifier = lisp_event->event.button.modifiers;
1397 if (modifier & MOD_SHIFT) state |= ShiftMask;
1398 if (modifier & MOD_CONTROL) state |= ControlMask;
1399 if (modifier & MOD_META) state |= xd->MetaMask;
1400 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1401 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1402 if (modifier & MOD_ALT) state |= xd->AltMask;
1403 state |= Button1Mask << (lisp_event->event.button.button-1);
1405 x_event.xbutton.state = state;
1406 x_event.xbutton.button = lisp_event->event.button.button;
1407 x_event.xkey.same_screen = True;
1409 DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len);
1413 /* the next thing blocks everything... */
1414 if (DndHandleDragging(wid, &x_event))
1420 #endif /* HAVE_OFFIX_DND */
1423 /************************************************************************/
1424 /* widget creation */
1425 /************************************************************************/
1427 /* The widget hierarchy is
1429 argv[0] shell container FRAME-NAME
1430 ApplicationShell EmacsShell EmacsManager EmacsFrame
1432 We accept geometry specs in this order:
1434 *FRAME-NAME.geometry
1435 *EmacsFrame.geometry
1438 Other possibilities for widget hierarchies might be
1440 argv[0] frame container FRAME-NAME
1441 ApplicationShell EmacsShell EmacsManager EmacsFrame
1443 argv[0] FRAME-NAME container FRAME-NAME
1444 ApplicationShell EmacsShell EmacsManager EmacsFrame
1446 argv[0] FRAME-NAME container emacsTextPane
1447 ApplicationShell EmacsShell EmacsManager EmacsFrame
1449 #ifdef EXTERNAL_WIDGET
1450 The ExternalShell widget is simply a replacement for the Shell widget
1451 which is able to deal with using an externally-supplied window instead
1452 of always creating its own.
1457 #ifdef EXTERNAL_WIDGET
1460 is_valid_window (Window w, struct device *d)
1462 XWindowAttributes xwa;
1463 Display *dpy = DEVICE_X_DISPLAY (d);
1465 expect_x_error (dpy);
1466 XGetWindowAttributes (dpy, w, &xwa);
1467 return !x_error_occurred_p (dpy);
1470 #endif /* EXTERNAL_WIDGET */
1472 /* This sends a synthetic mouse-motion event to the frame, if the mouse
1473 is over the frame. This ensures that the cursor gets set properly
1474 before the user moves the mouse for the first time. */
1477 x_send_synthetic_mouse_event (struct frame *f)
1479 /* #### write this function. */
1483 first_x_frame_p (struct frame *f)
1485 Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
1486 while (!NILP (rest) &&
1487 (f == XFRAME (XCAR (rest)) ||
1488 !FRAME_X_P (XFRAME (XCAR (rest)))))
1493 /* Figure out what size the EmacsFrame widget should initially be,
1494 and set it. Should be called after the default font has been
1495 determined but before the widget has been realized. */
1498 x_initialize_frame_size (struct frame *f)
1500 /* Geometry of the AppShell */
1504 unsigned int app_w = 0;
1505 unsigned int app_h = 0;
1507 /* Geometry of the EmacsFrame */
1508 int frame_flags = 0;
1511 unsigned int frame_w = 0;
1512 unsigned int frame_h = 0;
1514 /* Hairily merged geometry */
1517 unsigned int w = 80;
1518 unsigned int h = 40;
1521 char *geom = 0, *ew_geom = 0;
1522 Boolean iconic_p = False, ew_iconic_p = False;
1524 Widget wmshell = FRAME_X_SHELL_WIDGET (f);
1525 /* #### This may not be an ApplicationShell any more, with the 'popup
1527 Widget app_shell = XtParent (wmshell);
1528 Widget ew = FRAME_X_TEXT_WIDGET (f);
1530 /* set the position of the frame's root window now. When the
1531 frame was created, the position was initialized to (0,0). */
1533 struct window *win = XWINDOW (f->root_window);
1535 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1536 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
1538 if (!NILP (f->minibuffer_window))
1540 win = XWINDOW (f->minibuffer_window);
1541 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1545 #ifdef EXTERNAL_WIDGET
1546 /* If we're an external widget, then the size of the frame is predetermined
1547 (by the client) and is not our decision to make. */
1548 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1553 /* #### this junk has not been tested; therefore it's
1554 probably wrong. Doesn't really matter at this point because
1555 currently all frames are either top-level or external widgets. */
1557 /* If we're not our own top-level window, then we shouldn't go messing around
1558 with top-level shells or "Emacs.geometry" or any such stuff. Therefore,
1559 we do as follows to determine the size of the frame:
1561 1) If a value for the frame's "geometry" resource was specified, then
1562 use it. (This specifies a size in characters.)
1563 2) Else, if the "width" and "height" resources were specified, then
1564 leave them alone. (This is a value in pixels. Sorry, we can't break
1565 Xt conventions here.)
1566 3) Else, assume a size of 64x12. (This is somewhat arbitrary, but
1567 it's unlikely that a size of 80x40 is desirable because we're probably
1568 inside of a dialog box.)
1570 Set the widget's x, y, height, and width as determined. Don't set the
1571 top-level container widget, because we don't necessarily know what it
1572 is. (Assume it is smart and pays attention to our values.)
1575 if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
1577 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1579 frame_flags = XParseGeometry (ew_geom,
1581 &frame_w, &frame_h);
1582 if (! (frame_flags & (WidthValue | HeightValue)))
1585 XtSetArg (al [0], XtNwidth, &frame_w);
1586 XtSetArg (al [1], XtNheight, &frame_h);
1587 XtGetValues (ew, al, 2);
1588 if (!frame_w && !frame_h)
1592 frame_flags |= WidthValue | HeightValue;
1595 if (frame_flags & (WidthValue | HeightValue))
1596 EmacsFrameSetCharSize (ew, frame_w, frame_h);
1597 if (frame_flags & (XValue | YValue))
1600 XtSetArg (al [0], XtNwidth, &frame_w);
1601 XtSetArg (al [1], XtNheight, &frame_h);
1602 XtGetValues (ew, al, 2);
1604 if (frame_flags & XNegative)
1606 if (frame_flags & YNegative)
1609 XtSetArg (al [0], XtNx, frame_x);
1610 XtSetArg (al [1], XtNy, frame_y);
1611 XtSetValues (ew, al, 2);
1617 /* OK, we're a top-level shell. */
1619 if (!XtIsWMShell (wmshell))
1622 /* If the EmacsFrame doesn't have a geometry but the shell does,
1623 treat that as the geometry of the frame.
1624 (Is this bogus? I'm not sure.) */
1626 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1629 Xt_GET_VALUE (wmshell, XtNgeometry, &geom);
1633 Xt_SET_VALUE (ew, XtNgeometry, ew_geom);
1637 /* If the Shell is iconic, then the EmacsFrame is iconic.
1638 (Is this bogus? I'm not sure.) */
1639 Xt_GET_VALUE (ew, XtNiconic, &ew_iconic_p);
1642 Xt_GET_VALUE (wmshell, XtNiconic, &iconic_p);
1645 ew_iconic_p = iconic_p;
1646 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1650 Xt_GET_VALUE (app_shell, XtNgeometry, &geom);
1652 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
1655 frame_flags = XParseGeometry (ew_geom,
1657 &frame_w, &frame_h);
1659 if (first_x_frame_p (f))
1661 /* If this is the first frame created:
1662 ====================================
1664 - Use the ApplicationShell's size/position, if specified.
1665 (This is "Emacs.geometry", or the "-geometry" command line arg.)
1666 - Else use the EmacsFrame's size/position.
1667 (This is "*FRAME-NAME.geometry")
1669 - If the AppShell is iconic, the frame should be iconic.
1671 AppShell comes first so that -geometry always applies to the first
1672 frame created, even if there is an "every frame" entry in the
1675 if (app_flags & (XValue | YValue))
1677 x = app_x; y = app_y;
1678 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
1680 else if (frame_flags & (XValue | YValue))
1682 x = frame_x; y = frame_y;
1683 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1686 if (app_flags & (WidthValue | HeightValue))
1688 w = app_w; h = app_h;
1689 flags |= (app_flags & (WidthValue | HeightValue));
1691 else if (frame_flags & (WidthValue | HeightValue))
1693 w = frame_w; h = frame_h;
1694 flags |= (frame_flags & (WidthValue | HeightValue));
1697 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
1700 Xt_GET_VALUE (app_shell, XtNiconic, &iconic_p);
1703 ew_iconic_p = iconic_p;
1704 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1710 /* If this is not the first frame created:
1711 ========================================
1713 - use the EmacsFrame's size/position if specified
1714 - Otherwise, use the ApplicationShell's size, but not position.
1716 So that means that one can specify the position of the first frame
1717 with "Emacs.geometry" or `-geometry'; but can only specify the
1718 position of subsequent frames with "*FRAME-NAME.geometry".
1720 AppShell comes second so that -geometry does not apply to subsequent
1721 frames when there is an "every frame" entry in the resource db,
1722 but does apply to the first frame.
1724 if (frame_flags & (XValue | YValue))
1726 x = frame_x; y = frame_y;
1727 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1730 if (frame_flags & (WidthValue | HeightValue))
1732 w = frame_w; h = frame_h;
1733 flags |= (frame_flags & (WidthValue | HeightValue));
1735 else if (app_flags & (WidthValue | HeightValue))
1739 flags |= (app_flags & (WidthValue | HeightValue));
1743 x_set_initial_frame_size (f, flags, x, y, w, h);
1747 x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
1751 /* compute height of all top-area widgets */
1752 for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1754 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1755 if (wid && XtIsManaged (wid))
1756 *topbreadth += wid->core.height + 2*wid->core.border_width;
1761 x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
1763 struct frame *f = (struct frame *) client_data;
1764 EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
1765 Dimension width = emst->width;
1766 Dimension height = emst->height;
1767 Widget text = FRAME_X_TEXT_WIDGET (f);
1768 Dimension textbord = text->core.border_width;
1769 Dimension topbreadth;
1770 Position text_x = 0, text_y = 0;
1773 x_get_layout_sizes (f, &topbreadth);
1775 /* first the menubar and psheets ... */
1776 for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1778 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1779 if (wid && XtIsManaged (wid))
1781 Dimension bord = wid->core.border_width;
1782 XtConfigureWidget (wid, 0, text_y,
1783 width - 2*bord, wid->core.height,
1785 text_y += wid->core.height + 2*bord;
1789 #ifdef HAVE_SCROLLBARS
1790 f->scrollbar_y_offset = topbreadth + textbord;
1793 /* finally the text area */
1794 XtConfigureWidget (text, text_x, text_y,
1796 height - text_y - 2*textbord,
1801 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1803 struct frame *f = (struct frame *) client_data;
1804 EmacsManagerQueryGeometryStruct *emst =
1805 (EmacsManagerQueryGeometryStruct *) call_data;
1806 Widget text = FRAME_X_TEXT_WIDGET (f);
1807 Dimension textbord = text->core.border_width;
1808 Dimension topbreadth;
1809 XtWidgetGeometry req, repl;
1810 int mask = emst->request_mode & (CWWidth | CWHeight);
1812 x_get_layout_sizes (f, &topbreadth);
1814 /* Strip away menubar from suggested size, and ask the text widget
1815 what size it wants to be. */
1816 req.request_mode = mask;
1818 req.width = emst->proposed_width - 2*textbord;
1819 if (mask & CWHeight)
1820 req.height = emst->proposed_height - topbreadth - 2*textbord;
1821 XtQueryGeometry (text, &req, &repl);
1823 /* Now add the menubar back again */
1824 emst->proposed_width = repl.width + 2*textbord;
1825 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1828 /* Creates the widgets for a frame.
1829 lisp_window_id is a Lisp description of an X window or Xt
1832 This function does not create or map the windows. (That is
1833 done by x_popup_frame().)
1836 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1839 struct device *d = XDEVICE (f->device);
1840 Visual *visual = DEVICE_X_VISUAL (d);
1841 int depth = DEVICE_X_DEPTH (d);
1842 Colormap cmap = DEVICE_X_COLORMAP (d);
1843 #ifdef EXTERNAL_WIDGET
1844 Window window_id = 0;
1849 Widget text, container, shell;
1850 Widget parentwid = 0;
1851 #ifdef HAVE_MENUBARS
1852 int menubar_visible;
1856 if (STRINGP (f->name))
1857 GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, name);
1861 /* The widget hierarchy is
1863 argv[0] shell pane FRAME-NAME
1864 ApplicationShell EmacsShell EmacsManager EmacsFrame
1866 (the type of the shell is ExternalShell if this frame is running
1867 in another client's window)
1869 However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
1870 Normally such shells have name/class shellname/appclass, which in this
1871 case would be "shell/Emacs" instead of "frame-name/Emacs". We could
1872 also get around this by naming the shell "frame-name", but that would
1873 be confusing because the text area (the EmacsFrame widget inferior of
1874 the shell) is also called that. So we just set the WM_CLASS property.
1877 #ifndef EXTERNAL_WIDGET
1878 if (!NILP (lisp_window_id))
1879 error ("support for external widgets was not enabled at compile-time");
1881 if (!NILP (lisp_window_id))
1885 CHECK_STRING (lisp_window_id);
1886 string = (char *) (XSTRING_DATA (lisp_window_id));
1887 if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
1888 sscanf (string+2, "%lxu", &window_id);
1890 else if (string[0] == 'w')
1892 sscanf (string+1, "%x", &parent_widget);
1894 window_id = XtWindow (parent_widget);
1898 sscanf (string, "%lu", &window_id);
1899 if (!is_valid_window (window_id, d))
1900 error ("Invalid window %lu", (unsigned long) window_id);
1901 FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
1903 #endif /* EXTERNAL_WIDGET */
1904 FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
1907 XtSetArg (al[ac], XtNallowShellResize, True); ac++;
1908 #ifdef LWLIB_USES_MOTIF
1909 /* Motif sucks beans. Without this in here, it will delete the window
1910 out from under us when it receives a WM_DESTROY_WINDOW message
1912 XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1915 #ifdef EXTERNAL_WIDGET
1918 XtSetArg (al[ac], XtNwindow, window_id); ac++;
1921 #endif /* EXTERNAL_WIDGET */
1923 XtSetArg (al[ac], XtNinput, True); ac++;
1924 XtSetArg (al[ac], XtNminWidthCells, 10); ac++;
1925 XtSetArg (al[ac], XtNminHeightCells, 1); ac++;
1926 XtSetArg (al[ac], XtNvisual, visual); ac++;
1927 XtSetArg (al[ac], XtNdepth, depth); ac++;
1928 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1933 parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
1934 XtSetArg (al[ac], XtNtransientFor, parentwid); ac++;
1937 shell = XtCreatePopupShell ("shell",
1939 #ifdef EXTERNAL_WIDGET
1940 window_id ? externalShellWidgetClass :
1942 parentwid ? transientEmacsShellWidgetClass :
1943 topLevelEmacsShellWidgetClass
1945 parentwid ? parentwid :
1946 DEVICE_XT_APP_SHELL (d),
1948 FRAME_X_SHELL_WIDGET (f) = shell;
1949 maybe_set_frame_title_format (shell);
1951 /* Create the manager widget */
1953 XtSetArg (al[ac], XtNvisual, visual); ac++;
1954 XtSetArg (al[ac], XtNdepth, depth); ac++;
1955 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1957 container = XtCreateWidget ("container",
1958 emacsManagerWidgetClass, shell, al, ac);
1959 FRAME_X_CONTAINER_WIDGET (f) = container;
1960 XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
1962 XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
1965 /* Create the text area */
1967 XtSetArg (al[ac], XtNvisual, visual); ac++;
1968 XtSetArg (al[ac], XtNdepth, depth); ac++;
1969 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1970 XtSetArg (al[ac], XtNborderWidth, 0); ac++; /* should this be settable? */
1971 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
1972 text = XtCreateWidget (name, emacsFrameClass, container, al, ac);
1973 FRAME_X_TEXT_WIDGET (f) = text;
1975 #ifdef HAVE_MENUBARS
1976 /* Create the initial menubar widget. */
1977 menubar_visible = x_initialize_frame_menubar (f);
1978 FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
1979 FRAME_X_NUM_TOP_WIDGETS (f) = 1;
1981 if (menubar_visible)
1982 XtManageChild (menubar);
1983 #endif /* HAVE_MENUBARS */
1984 XtManageChild (text);
1985 XtManageChild (container);
1988 /* We used to call XtPopup() in x_popup_frame, but that doesn't give
1989 you control over whether the widget is initially mapped or not
1990 because XtPopup() makes an unconditional call to XMapRaised().
1991 Boy, those Xt designers were clever.
1993 When we first removed it we only kept the XtRealizeWidget call in
1994 XtPopup. For everything except HP's that was enough. For HP's,
1995 though, the failure to call the popup callbacks resulted in XEmacs
1996 not accepting any input. Bizarre but true. Stupid but true.
1998 So, in case there are any other gotches floating out there along
1999 the same lines I've duplicated the majority of XtPopup here. It
2000 assumes no grabs and that the widget is not already popped up, both
2001 valid assumptions for the one place this is called from. */
2003 xemacs_XtPopup (Widget widget)
2005 ShellWidget shell_widget = (ShellWidget) widget;
2006 XtGrabKind call_data = XtGrabNone;
2008 XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data);
2010 shell_widget->shell.popped_up = TRUE;
2011 shell_widget->shell.grab_kind = XtGrabNone;
2012 shell_widget->shell.spring_loaded = False;
2014 if (shell_widget->shell.create_popup_child_proc != NULL)
2015 (*(shell_widget->shell.create_popup_child_proc))(widget);
2017 /* The XtSetValues below are not in XtPopup menu. We just want to
2018 make absolutely sure... */
2019 Xt_SET_VALUE (widget, XtNmappedWhenManaged, False);
2020 XtRealizeWidget (widget);
2021 Xt_SET_VALUE (widget, XtNmappedWhenManaged, True);
2025 /* Does this have to be non-automatic? */
2026 /* hack frame to respond to dnd messages */
2027 static XtCallbackRec dnd_transfer_cb_rec[2];
2028 #endif /* HAVE_CDE */
2030 /* create the windows for the specified frame and display them.
2031 Note that the widgets have already been created, and any
2032 necessary geometry calculations have already been done. */
2034 x_popup_frame (struct frame *f)
2036 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
2037 Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
2038 struct device *d = XDEVICE (FRAME_DEVICE (f));
2040 /* Before mapping the window, make sure that the WMShell's notion of
2041 whether it should be iconified is synchronized with the EmacsFrame's
2044 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2045 x_wm_set_shell_iconic_p (shell_widget,
2046 ((EmacsFrame) frame_widget)
2047 ->emacs_frame.iconic);
2049 xemacs_XtPopup (shell_widget);
2051 if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
2052 XtMapWidget (shell_widget);
2055 /* We may have set f->visible to 1 in x_init_frame(), so undo
2057 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
2061 #ifdef EXTERNAL_WIDGET
2062 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2063 ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
2066 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2068 /* tell the window manager about us. */
2069 x_wm_store_class_hints (shell_widget, XtName (frame_widget));
2071 #ifndef HAVE_SESSION
2072 x_wm_maybe_store_wm_command (f);
2073 #endif /* HAVE_SESSION */
2075 x_wm_hack_wm_protocols (shell_widget);
2080 #endif /* HAVE_XIM */
2083 /* Allow XEmacs to respond to EditRes requests. See the O'Reilly Xt */
2084 /* Instrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
2086 XtAddEventHandler (shell_widget, /* the shell widget in question */
2087 (EventMask) NoEventMask,/* OR with existing mask */
2088 True, /* called on non-maskable events? */
2089 (XtEventHandler) _XEditResCheckMessages, /* the handler */
2091 #endif /* HACK_EDITRES */
2095 dnd_transfer_cb_rec[0].callback = x_cde_transfer_callback;
2096 dnd_transfer_cb_rec[0].closure = (XtPointer) f;
2097 dnd_transfer_cb_rec[1].callback = NULL;
2098 dnd_transfer_cb_rec[1].closure = NULL;
2100 DtDndVaDropRegister (FRAME_X_TEXT_WIDGET (f),
2101 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
2102 XmDROP_COPY, dnd_transfer_cb_rec,
2103 DtNtextIsBuffer, True,
2104 DtNregisterChildren, True,
2105 DtNpreserveRegistration, False,
2108 #endif /* HAVE_CDE */
2110 /* Do a stupid property change to force the server to generate a
2111 propertyNotify event so that the event_stream server timestamp will
2112 be initialized to something relevant to the time we created the window.
2114 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2115 DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
2116 (unsigned char*) NULL, 0);
2118 x_send_synthetic_mouse_event (f);
2122 allocate_x_frame_struct (struct frame *f)
2124 /* zero out all slots. */
2125 f->frame_data = xnew_and_zero (struct x_frame);
2127 /* yeah, except the lisp ones */
2128 FRAME_X_ICON_PIXMAP (f) = Qnil;
2129 FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
2133 /************************************************************************/
2134 /* Lisp functions */
2135 /************************************************************************/
2138 x_init_frame_1 (struct frame *f, Lisp_Object props)
2140 /* This function can GC */
2141 Lisp_Object device = FRAME_DEVICE (f);
2142 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
2143 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
2148 popup = Fselected_frame (device);
2149 CHECK_LIVE_FRAME (popup);
2150 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
2151 signal_simple_error_2 ("Parent must be on same device as frame",
2156 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
2157 * to make sure that messages were displayed as soon as possible
2158 * if we're creating the first frame on a device. But it is
2159 * better to just set this all the time, so that when a new frame
2160 * is created that covers the selected frame, echo area status
2161 * messages can still be seen. f->visible is reset later if the
2162 * initially-unmapped property is found to be non-nil in the
2167 allocate_x_frame_struct (f);
2168 x_create_widgets (f, lisp_window_id, popup);
2172 x_init_frame_2 (struct frame *f, Lisp_Object props)
2174 /* Set up the values of the widget/frame. A case could be made for putting
2175 this inside of the widget's initialize method. */
2177 update_frame_face_values (f);
2178 x_initialize_frame_size (f);
2180 * update_frame_title() can't be done here, because some of the
2181 * modeline specs depend on the frame's device having a selected
2182 * frame, and that may not have been set up yet. The redisplay
2183 * will update the frame title anyway, so nothing is lost.
2185 * It turns out it gives problems with FVWMs name based mapping.
2186 * We'll just need to be carefull in the modeline specs.
2188 update_frame_title (f);
2192 x_init_frame_3 (struct frame *f)
2194 /* Pop up the frame. */
2200 x_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
2202 ((markobj) (FRAME_X_ICON_PIXMAP (f)));
2203 ((markobj) (FRAME_X_ICON_PIXMAP_MASK (f)));
2207 x_set_frame_icon (struct frame *f)
2209 Pixmap x_pixmap, x_mask;
2211 if (IMAGE_INSTANCEP (f->icon)
2212 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
2214 x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (f->icon);
2215 x_mask = XIMAGE_INSTANCE_X_MASK (f->icon);
2223 /* Store the X data into the widget. */
2226 XtSetArg (al [0], XtNiconPixmap, x_pixmap);
2227 XtSetArg (al [1], XtNiconMask, x_mask);
2228 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
2233 x_set_frame_pointer (struct frame *f)
2235 XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
2236 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2237 XIMAGE_INSTANCE_X_CURSOR (f->pointer));
2238 XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
2242 x_get_frame_parent (struct frame *f)
2244 Widget parentwid = 0;
2246 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNtransientFor, &parentwid);
2247 /* find the frame whose wid is parentwid */
2250 Lisp_Object frmcons;
2251 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
2253 Lisp_Object frame = XCAR (frmcons);
2254 if (FRAME_X_SHELL_WIDGET (XFRAME (frame)) == parentwid)
2261 DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
2262 Get the ID of the X11 window.
2263 This gives us a chance to manipulate the Emacs window from within a
2264 different program. Since the ID is an unsigned long, we return it as
2270 struct frame *f = decode_x_frame (frame);
2272 sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
2273 return build_string (str);
2277 /************************************************************************/
2278 /* manipulating the X window */
2279 /************************************************************************/
2282 x_set_frame_position (struct frame *f, int xoff, int yoff)
2284 Widget w = FRAME_X_SHELL_WIDGET (f);
2285 Display *dpy = XtDisplay (w);
2286 Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
2287 Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
2288 Dimension shell_w, shell_h, shell_bord;
2292 XtSetArg (al [0], XtNwidth, &shell_w);
2293 XtSetArg (al [1], XtNheight, &shell_h);
2294 XtSetArg (al [2], XtNborderWidth, &shell_bord);
2295 XtGetValues (w, al, 3);
2298 xoff >= 0 && yoff >= 0 ? NorthWestGravity :
2299 xoff >= 0 ? SouthWestGravity :
2300 yoff >= 0 ? NorthEastGravity :
2303 xoff += frame_w - shell_w - 2*shell_bord;
2305 yoff += frame_h - shell_h - 2*shell_bord;
2307 /* Update the hints so that, if this window is currently iconified, it will
2308 come back at the right place. We can't look at s->visible to determine
2309 whether it is iconified because it might not be up-to-date yet (the queue
2310 might not be processed). */
2311 XtSetArg (al [0], XtNwinGravity, win_gravity);
2312 XtSetArg (al [1], XtNx, xoff);
2313 XtSetArg (al [2], XtNy, yoff);
2314 XtSetValues (w, al, 3);
2316 /* Sometimes you will find that
2318 (set-frame-position (selected-frame) -50 -50)
2320 doesn't put the frame where you expect it to: i.e. it's closer to
2321 the lower-right corner than it should be, and it appears that the
2322 size of the WM decorations was not taken into account. This is
2323 *not* a problem with this function. Both mwm and twm have bugs
2324 in handling this situation. (mwm ignores the window gravity and
2325 always assumes NorthWest, except the first time you map the
2326 window; twm gets things almost right, but forgets to account for
2327 the border width of the top-level window.) This function does
2328 what it's supposed to according to the ICCCM, and I'm not about
2329 to hack around window-manager bugs. */
2332 /* This is not necessary under either mwm or twm */
2333 x_wm_mark_shell_position_user_specified (w);
2337 /* Call this to change the size of frame S's x-window. */
2340 x_set_frame_size (struct frame *f, int cols, int rows)
2342 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
2344 /* this is not correct. x_set_frame_size() is called from
2345 Fset_frame_size(), which may or may not have been called
2346 by the user (e.g. update_EmacsFrame() calls it when the font
2347 changes). For now, don't bother with getting this right. */
2348 x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
2353 x_set_mouse_position (struct window *w, int x, int y)
2355 struct frame *f = XFRAME (w->frame);
2357 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2358 XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
2359 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
2363 x_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
2365 Display *display = DEVICE_X_DISPLAY (d);
2366 Window child_window;
2371 unsigned int keys_and_buttons;
2374 if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
2375 &root_window, &child_window, &root_x, &root_y,
2376 &win_x, &win_y, &keys_and_buttons) == False)
2379 if (child_window == None)
2380 return 0; /* not over any window. */
2385 if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
2386 &win_x, &win_y, &child_window) == False)
2390 if (child_window == None)
2394 /* At this point, win is the innermost window containing the pointer
2395 and win_x and win_y are the coordinates of that window. */
2396 f = x_any_window_to_frame (d, win);
2399 XSETFRAME (*frame, f);
2401 if (XTranslateCoordinates (display, win,
2402 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2403 win_x, win_y, x, y, &child_window) == False)
2411 x_cant_notify_wm_error (void)
2413 error ("Can't notify window manager of iconification.");
2416 /* Raise frame F. */
2418 x_raise_frame_1 (struct frame *f, int force)
2420 if (FRAME_VISIBLE_P (f) || force)
2422 Widget bottom_dialog;
2425 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2426 Window emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
2428 /* first raises all the dialog boxes, then put emacs just below the
2429 * bottom most dialog box */
2430 bottom_dialog = lw_raise_all_pop_up_widgets ();
2431 if (bottom_dialog && XtWindow (bottom_dialog))
2433 xwc.sibling = XtWindow (bottom_dialog);
2434 xwc.stack_mode = Below;
2435 flags = CWSibling | CWStackMode;
2439 xwc.stack_mode = Above;
2440 flags = CWStackMode;
2443 if (!XReconfigureWMWindow (display, emacs_window,
2444 DefaultScreen (display),
2446 x_cant_notify_wm_error ();
2451 x_raise_frame (struct frame *f)
2453 x_raise_frame_1 (f, 1);
2456 /* Lower frame F. */
2458 x_lower_frame (struct frame *f)
2460 if (FRAME_VISIBLE_P (f))
2462 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2464 unsigned int flags = CWStackMode;
2466 xwc.stack_mode = Below;
2467 if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
2468 DefaultScreen (display), flags, &xwc))
2469 x_cant_notify_wm_error ();
2473 /* Change from withdrawn state to mapped state. */
2475 x_make_frame_visible (struct frame *f)
2477 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2479 if (!FRAME_VISIBLE_P(f))
2480 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2482 x_raise_frame_1 (f, 0);
2485 /* Change from mapped state to withdrawn state. */
2487 x_make_frame_invisible (struct frame *f)
2489 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2491 if (!FRAME_VISIBLE_P(f))
2494 if (!XWithdrawWindow (display,
2495 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2496 DefaultScreen (display)))
2497 x_cant_notify_wm_error ();
2501 x_frame_visible_p (struct frame *f)
2504 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2505 XWindowAttributes xwa;
2509 This is bad, very bad :-(
2510 It is not compatible with our tristate visible and
2511 it should never ever change the visibility for us, this leads to
2512 the frame-freeze problem under fvwm because with the pager
2514 Mappedness != Viewability != Visibility != Emacs f->visible
2516 This first unequalness is the reason for the frame freezing problem
2517 under fvwm (it happens when the frame is another fvwm-page)
2519 The second unequalness happen when it is on the same fvwm-page
2520 but in an invisible part of the visible screen.
2522 For now we just return the XEmacs internal value --- which might not be up
2523 to date. Is that a problem? ---. Otherwise we should
2524 use async visibility like in standard Emacs.
2527 if (!XGetWindowAttributes (display,
2528 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2532 result = xwa.map_state == IsViewable;
2533 /* In this implementation it should at least be != IsUnmapped
2536 f->visible = result;
2544 x_frame_totally_visible_p (struct frame *f)
2546 return FRAME_X_TOTALLY_VISIBLE_P (f);
2549 /* Change window state from mapped to iconified. */
2551 x_iconify_frame (struct frame *f)
2553 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2555 if (!XIconifyWindow (display,
2556 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2557 DefaultScreen (display)))
2558 x_cant_notify_wm_error ();
2563 /* Sets the X focus to frame f. */
2565 x_focus_on_frame (struct frame *f)
2567 XWindowAttributes xwa;
2568 Widget shell_widget;
2571 assert (FRAME_X_P (f));
2573 shell_widget = FRAME_X_SHELL_WIDGET (f);
2574 if (!XtWindow (shell_widget))
2577 #ifdef EXTERNAL_WIDGET
2578 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2579 ExternalShellSetFocus (shell_widget);
2580 #endif /* EXTERNAL_WIDGET */
2582 /* Do the ICCCM focus change if the window is still visible.
2583 The s->visible flag might not be up-to-date, because we might
2584 not have processed magic events recently. So make a server
2585 round-trip to find out whether it's really mapped right now.
2586 We grab the server to do this, because that's the only way to
2587 eliminate the race condition.
2589 XGrabServer (XtDisplay (shell_widget));
2590 if (XGetWindowAttributes (XtDisplay (shell_widget),
2591 XtWindow (shell_widget),
2593 /* JV: it is bad to change the visibility like this, so we don't for the
2594 moment, at least change_frame_visibility should be called
2595 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2596 but still X-invisible
2597 f->visible = xwa.map_state == IsViewable; */
2598 viewable = xwa.map_state == IsViewable;
2605 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2606 /* Don't explicitly set the focus on this window unless the focus
2607 was on some other window (not PointerRoot). Note that, even when
2608 running a point-to-type window manager like *twm, there is always
2609 a focus window; the window manager maintains that based on the
2610 mouse position. If you set the "NoTitleFocus" option in these
2611 window managers, then the server itself maintains the focus via
2612 PointerRoot, and changing that to focus on the window would make
2613 the window grab the focus. Very bad.
2615 if (focus != PointerRoot)
2617 XSetInputFocus (XtDisplay (shell_widget),
2618 XtWindow (shell_widget),
2620 DEVICE_X_MOUSE_TIMESTAMP
2621 (XDEVICE (FRAME_DEVICE (f))));
2622 XFlush (XtDisplay (shell_widget));
2625 XUngrabServer (XtDisplay (shell_widget));
2626 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2629 /* Destroy the X window of frame S. */
2631 x_delete_frame (struct frame *f)
2633 Widget w = FRAME_X_SHELL_WIDGET (f);
2634 Display *dpy = XtDisplay (w);
2636 #ifndef HAVE_SESSION
2637 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2638 x_wm_maybe_move_wm_command (f);
2639 #endif /* HAVE_SESSION */
2641 #ifdef EXTERNAL_WIDGET
2642 expect_x_error (dpy);
2643 /* for obscure reasons having (I think) to do with the internal
2644 window-to-widget hierarchy maintained by Xt, we have to call
2645 XtUnrealizeWidget() here. Xt can really suck. */
2646 if (f->being_deleted)
2647 XtUnrealizeWidget (w);
2648 XtDestroyWidget (w);
2649 x_error_occurred_p (dpy);
2651 XtDestroyWidget (w);
2652 XFlush (dpy); /* make sure the windows are really gone! */
2653 #endif /* EXTERNAL_WIDGET */
2655 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2656 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2657 xfree (f->frame_data);
2662 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2666 Lisp_Object frame = Qnil;
2668 XSETFRAME(frame, frm);
2670 if (EQ (name, Qforeground))
2672 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2675 if (!EQ (color, Vthe_null_color_instance))
2677 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2678 XtSetArg (av[ac], XtNforeground, (void *) fgc.pixel); ac++;
2681 else if (EQ (name, Qbackground))
2683 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2686 if (!EQ (color, Vthe_null_color_instance))
2688 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2689 XtSetArg (av[ac], XtNbackground, (void *) bgc.pixel); ac++;
2692 /* Really crappy way to force the modeline shadows to be
2693 redrawn. But effective. */
2694 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2695 MARK_FRAME_CHANGED (frm);
2697 else if (EQ (name, Qfont))
2699 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2701 if (!EQ (font, Vthe_null_font_instance))
2702 XtSetArg (av[ac], XtNfont,
2703 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2709 XtSetValues (FRAME_X_TEXT_WIDGET (frm), av, ac);
2711 #ifdef HAVE_TOOLBARS
2712 /* Setting the background clears the entire frame area
2713 including the toolbar so we force an immediate redraw of
2715 if (EQ (name, Qbackground))
2716 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2717 #endif /* HAVE_TOOLBARS */
2719 /* Set window manager resize increment hints according to
2720 the new character size */
2721 if (EQ (name, Qfont))
2722 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2726 /************************************************************************/
2727 /* initialization */
2728 /************************************************************************/
2731 syms_of_frame_x (void)
2733 defsymbol (&Qwindow_id, "window-id");
2734 defsymbol (&Qx_resource_name, "x-resource-name");
2736 DEFSUBR (Fx_window_id);
2738 DEFSUBR (Fcde_start_drag_internal);
2740 #ifdef HAVE_OFFIX_DND
2741 DEFSUBR (Foffix_start_drag_internal);
2746 console_type_create_frame_x (void)
2749 CONSOLE_HAS_METHOD (x, init_frame_1);
2750 CONSOLE_HAS_METHOD (x, init_frame_2);
2751 CONSOLE_HAS_METHOD (x, init_frame_3);
2752 CONSOLE_HAS_METHOD (x, mark_frame);
2753 CONSOLE_HAS_METHOD (x, focus_on_frame);
2754 CONSOLE_HAS_METHOD (x, delete_frame);
2755 CONSOLE_HAS_METHOD (x, get_mouse_position);
2756 CONSOLE_HAS_METHOD (x, set_mouse_position);
2757 CONSOLE_HAS_METHOD (x, raise_frame);
2758 CONSOLE_HAS_METHOD (x, lower_frame);
2759 CONSOLE_HAS_METHOD (x, make_frame_visible);
2760 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2761 CONSOLE_HAS_METHOD (x, iconify_frame);
2762 CONSOLE_HAS_METHOD (x, set_frame_size);
2763 CONSOLE_HAS_METHOD (x, set_frame_position);
2764 CONSOLE_HAS_METHOD (x, frame_property);
2765 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2766 CONSOLE_HAS_METHOD (x, frame_properties);
2767 CONSOLE_HAS_METHOD (x, set_frame_properties);
2768 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2769 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2770 CONSOLE_HAS_METHOD (x, frame_visible_p);
2771 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2772 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2773 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2774 CONSOLE_HAS_METHOD (x, set_frame_icon);
2775 CONSOLE_HAS_METHOD (x, get_frame_parent);
2776 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2780 vars_of_frame_x (void)
2782 #ifdef EXTERNAL_WIDGET
2783 Fprovide (intern ("external-widget"));
2786 /* this call uses only safe functions from emacs.c */
2787 init_x_prop_symbols ();
2789 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2790 Plist of default frame-creation properties for X frames.
2791 These override what is specified in the resource database and in
2792 `default-frame-plist', but are overridden by the arguments to the
2793 particular call to `make-frame'.
2795 Note: In many cases, properties of a frame are available as specifiers
2796 instead of through the frame-properties mechanism.
2798 Here is a list of recognized frame properties, other than those
2799 documented in `set-frame-properties' (they can be queried and
2800 set at any time, except as otherwise noted):
2802 window-id The X window ID corresponding to the
2803 frame. May be set only at startup, and
2804 only if external widget support was
2805 compiled in; doing so causes the frame
2806 to be created as an "external widget"
2807 in another program that uses an existing
2808 window in the program rather than creating
2810 initially-unmapped If non-nil, the frame will not be visible
2811 when it is created. In this case, you
2812 need to call `make-frame-visible' to make
2814 popup If non-nil, it should be a frame, and this
2815 frame will be created as a "popup" frame
2816 whose parent is the given frame. This
2817 will make the window manager treat the
2818 frame as a dialog box, which may entail
2819 doing different things (e.g. not asking
2820 for positioning, and not iconifying
2821 separate from its parent).
2822 inter-line-space Not currently implemented.
2823 toolbar-shadow-thickness Thickness of toolbar shadows.
2824 background-toolbar-color Color of toolbar background.
2825 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2826 (*Not* specific to the bottom-toolbar.)
2827 top-toolbar-shadow-color Color of top shadows on toolbars.
2828 (*Not* specific to the top-toolbar.)
2829 internal-border-width Width of internal border around text area.
2830 border-width Width of external border around text area.
2831 top Y position (in pixels) of the upper-left
2832 outermost corner of the frame (i.e. the
2833 upper-left of the window-manager
2835 left X position (in pixels) of the upper-left
2836 outermost corner of the frame (i.e. the
2837 upper-left of the window-manager
2839 border-color Color of external border around text area.
2840 cursor-color Color of text cursor.
2842 See also `default-frame-plist', which specifies properties which apply
2843 to all frames, not just X frames.
2845 Vdefault_x_frame_plist = Qnil;
2847 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;