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 assert (XtIsWMShell (widget));
284 Atom type, *atoms = 0;
286 unsigned long nitems = 0;
287 unsigned long bytes_after;
289 if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d),
290 0, 100, False, XA_ATOM,
291 &type, &format, &nitems, &bytes_after,
292 (unsigned char **) &atoms)
293 && format == 32 && type == XA_ATOM)
297 if (atoms [nitems] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
299 else if (atoms [nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
302 if (atoms) XFree ((char *) atoms);
307 if (need_delete) props[count++] = DEVICE_XATOM_WM_DELETE_WINDOW (d);
308 if (need_focus) props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d);
310 XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32,
311 PropModeAppend, (unsigned char *) props, count);
316 x_wm_store_class_hints (Widget shell, char *frame_name)
318 Display *dpy = XtDisplay (shell);
319 char *app_name, *app_class;
320 XClassHint classhint;
322 if (!XtIsWMShell (shell))
325 XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
326 classhint.res_name = frame_name;
327 classhint.res_class = app_class;
328 XSetClassHint (dpy, XtWindow (shell), &classhint);
333 x_wm_maybe_store_wm_command (struct frame *f)
335 Widget w = FRAME_X_SHELL_WIDGET (f);
336 struct device *d = XDEVICE (FRAME_DEVICE (f));
338 if (!XtIsWMShell (w))
341 if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
345 make_argc_argv (Vcommand_line_args, &argc, &argv);
346 XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
347 free_argc_argv (argv);
348 XSETFRAME (DEVICE_X_WM_COMMAND_FRAME (d), f);
352 /* If we're deleting the frame on which the WM_COMMAND property has been
353 set, then move that property to another frame so that there is exactly
354 one frame that has that property set.
357 x_wm_maybe_move_wm_command (struct frame *f)
359 struct device *d = XDEVICE (FRAME_DEVICE (f));
361 /* There may not be a frame in DEVICE_X_WM_COMMAND_FRAME()
362 if we C-c'ed at startup at the right time. */
363 if (FRAMEP (DEVICE_X_WM_COMMAND_FRAME (d))
364 && f == XFRAME (DEVICE_X_WM_COMMAND_FRAME (d)))
366 Lisp_Object rest = DEVICE_FRAME_LIST (d);
367 DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
368 /* find some random other X frame that is not this one, or give up */
369 /* skip non-top-level (ExternalClient) frames */
370 while (!NILP (rest) &&
371 (f == XFRAME (XCAR (rest)) ||
372 !FRAME_X_TOP_LEVEL_FRAME_P (XFRAME (XCAR (rest)))))
376 f = XFRAME (XCAR (rest));
378 x_wm_maybe_store_wm_command (f);
382 #endif /* !HAVE_SESSION */
385 x_frame_iconified_p (struct frame *f)
389 unsigned long nitems, bytesafter;
390 unsigned long *datap = 0;
393 struct device *d = XDEVICE (FRAME_DEVICE (f));
395 widget = FRAME_X_SHELL_WIDGET (f);
396 if (Success == XGetWindowProperty (XtDisplay (widget), XtWindow (widget),
397 DEVICE_XATOM_WM_STATE (d), 0, 2, False,
398 DEVICE_XATOM_WM_STATE (d), &actual_type,
399 &actual_format, &nitems, &bytesafter,
400 (unsigned char **) &datap)
403 if (nitems <= 2 /* "suggested" by ICCCM version 1 */
404 && datap[0] == IconicState)
406 XFree ((char *) datap);
412 /************************************************************************/
413 /* frame properties */
414 /************************************************************************/
416 /* Connect the frame-property names (symbols) to the corresponding
417 X Resource Manager names. The name of a property, as a Lisp symbol,
418 has an `x-resource-name' property which is a Lisp_String. */
421 init_x_prop_symbols (void)
423 #define def(sym, rsrc) \
424 pure_put (sym, Qx_resource_name, build_string (rsrc))
425 #define defi(sym,rsrc) \
426 def (sym, rsrc); pure_put (sym, Qintegerp, Qt)
428 #if 0 /* this interferes with things. #### fix this right */
429 def (Qminibuffer, XtNminibuffer);
430 def (Qunsplittable, XtNunsplittable);
432 defi(Qinternal_border_width, XtNinternalBorderWidth);
434 def (Qtop_toolbar_shadow_color, XtNtopToolBarShadowColor);
435 def (Qbottom_toolbar_shadow_color, XtNbottomToolBarShadowColor);
436 def (Qbackground_toolbar_color, XtNbackgroundToolBarColor);
437 def (Qtop_toolbar_shadow_pixmap, XtNtopToolBarShadowPixmap);
438 def (Qbottom_toolbar_shadow_pixmap, XtNbottomToolBarShadowPixmap);
439 defi(Qtoolbar_shadow_thickness, XtNtoolBarShadowThickness);
441 def (Qscrollbar_placement, XtNscrollBarPlacement);
442 defi(Qinter_line_space, XtNinterline);
443 /* font, foreground */
444 def (Qiconic, XtNiconic);
445 def (Qbar_cursor, XtNbarCursor);
446 def (Qvisual_bell, XtNvisualBell);
447 defi(Qbell_volume, XtNbellVolume);
448 def (Qpointer_background, XtNpointerBackground);
449 def (Qpointer_color, XtNpointerColor);
450 def (Qtext_pointer, XtNtextPointer);
451 def (Qspace_pointer, XtNspacePointer);
452 def (Qmodeline_pointer, XtNmodeLinePointer);
453 def (Qgc_pointer, XtNgcPointer);
454 /* geometry, initial_geometry */
455 def (Qinitially_unmapped, XtNinitiallyUnmapped);
456 /* preferred_width, preferred_height */
457 def (Quse_backing_store, XtNuseBackingStore);
461 def (Qborder_color, XtNborderColor);
462 defi(Qborder_width, XtNborderWidth);
463 defi(Qwidth, XtNwidth);
464 defi(Qheight, XtNheight);
472 color_to_string (Widget w, unsigned long pixel)
478 XQueryColor (XtDisplay (w), w->core.colormap, &color);
479 sprintf (buf, "#%04x%04x%04x", color.red, color.green, color.blue);
480 return build_string (buf);
484 x_get_top_level_position (Display *d, Window w, Position *x, Position *y)
486 Window root, parent = w, *children;
487 unsigned int nchildren;
488 XWindowAttributes xwa;
493 if (!XQueryTree (d, w, &root, &parent, &children, &nchildren))
501 while (root != parent);
502 XGetWindowAttributes (d, w, &xwa);
509 x_smash_bastardly_shell_position (Widget shell)
511 /* Naturally those bastards who wrote Xt couldn't be bothered
512 to learn about race conditions and such. We can't trust
513 the X and Y values to have any semblance of correctness,
514 so we smash the right values in place. */
516 /* We might be called before we've actually realized the window (if
517 we're checking for the minibuffer resource). This will bomb in
518 that case so we don't bother calling it. */
519 if (XtWindow (shell))
520 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
521 &shell->core.x, &shell->core.y);
526 x_frame_property (struct frame *f, Lisp_Object property)
528 Widget shell = FRAME_X_SHELL_WIDGET (f);
529 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
530 Widget gw = (Widget) w;
532 if (EQ (Qleft, property) || EQ (Qtop, property))
535 if (!XtWindow(shell))
537 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
538 if (EQ (Qleft, property)) return make_int (x);
539 if (EQ (Qtop, property)) return make_int (y);
541 if (EQ (Qborder_width, property))
542 return make_int (w->core.border_width);
543 if (EQ (Qinternal_border_width, property))
544 return make_int (w->emacs_frame.internal_border_width);
545 if (EQ (Qborder_color, property))
546 return color_to_string (gw, w->core.border_pixel);
548 if (EQ (Qtop_toolbar_shadow_color, property))
549 return color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel);
550 if (EQ (Qbottom_toolbar_shadow_color, property))
551 return color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel);
552 if (EQ (Qbackground_toolbar_color, property))
553 return color_to_string (gw, w->emacs_frame.background_toolbar_pixel);
554 if (EQ (Qtoolbar_shadow_thickness, property))
555 return make_int (w->emacs_frame.toolbar_shadow_thickness);
556 #endif /* HAVE_TOOLBARS */
557 if (EQ (Qinter_line_space, property))
558 return make_int (w->emacs_frame.interline);
559 if (EQ (Qwindow_id, property))
560 return Fx_window_id (make_frame (f));
566 x_internal_frame_property_p (struct frame *f, Lisp_Object property)
568 return EQ (property, Qleft)
569 || EQ (property, Qtop)
570 || EQ (property, Qborder_width)
571 || EQ (property, Qinternal_border_width)
572 || EQ (property, Qborder_color)
574 || EQ (property, Qtop_toolbar_shadow_color)
575 || EQ (property, Qbottom_toolbar_shadow_color)
576 || EQ (property, Qbackground_toolbar_color)
577 || EQ (property, Qtoolbar_shadow_thickness)
578 #endif /* HAVE_TOOLBARS */
579 || EQ (property, Qinter_line_space)
580 || EQ (property, Qwindow_id)
581 || STRINGP (property);
585 x_frame_properties (struct frame *f)
587 Lisp_Object props = Qnil;
588 Widget shell = FRAME_X_SHELL_WIDGET (f);
589 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
590 Widget gw = (Widget) w;
593 props = cons3 (Qwindow_id, Fx_window_id (make_frame (f)), props);
594 props = cons3 (Qinter_line_space, make_int (w->emacs_frame.interline), props);
597 props = cons3 (Qtoolbar_shadow_thickness,
598 make_int (w->emacs_frame.toolbar_shadow_thickness),
600 props = cons3 (Qbackground_toolbar_color,
601 color_to_string (gw, w->emacs_frame.background_toolbar_pixel),
603 props = cons3 (Qbottom_toolbar_shadow_color,
604 color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel),
606 props = cons3 (Qtop_toolbar_shadow_color,
607 color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel),
609 #endif /* HAVE_TOOLBARS */
611 props = cons3 (Qborder_color,
612 color_to_string (gw, w->core.border_pixel), props);
613 props = cons3 (Qinternal_border_width,
614 make_int (w->emacs_frame.internal_border_width), props);
615 props = cons3 (Qborder_width, make_int (w->core.border_width), props);
617 if (!XtWindow(shell))
620 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
622 props = cons3 (Qtop, make_int (y), props);
623 props = cons3 (Qleft, make_int (x), props);
629 /* Functions called only from `x_set_frame_properties' to set
630 individual properties. */
633 x_set_frame_text_value (struct frame *f, Bufbyte *value,
634 String Xt_resource_name,
635 String Xt_resource_encoding_name)
637 Atom encoding = XA_STRING;
638 String new_XtValue = (String) value;
639 String old_XtValue = NULL;
643 /* Optimize for common ASCII case */
644 for (ptr = value; *ptr; ptr++)
645 if (!BYTE_ASCII_P (*ptr))
648 encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f)));
649 GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA ((CONST char *) value, tmp);
650 new_XtValue = (String) tmp;
655 /* ### Caching is device-independent - belongs in update_frame_title. */
656 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
657 if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
660 XtSetArg (al[0], Xt_resource_name, new_XtValue);
661 XtSetArg (al[1], Xt_resource_encoding_name, encoding);
662 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
667 x_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
669 x_set_frame_text_value (f, name, XtNtitle, XtNtitleEncoding);
673 x_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
675 x_set_frame_text_value (f, name, XtNiconName, XtNiconNameEncoding);
678 /* Set the initial frame size as specified. This function is used
679 when the frame's widgets have not yet been realized. In this
680 case, it is not sufficient just to set the width and height of
681 the EmacsFrame widget, because they will be ignored when the
682 widget is realized (instead, the shell's geometry resource is
686 x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
687 unsigned int w, unsigned int h)
689 char shell_geom [255];
692 char uspos = !!(flags & (XValue | YValue));
693 char ussize = !!(flags & (WidthValue | HeightValue));
696 /* assign the correct size to the EmacsFrame widget ... */
697 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
699 /* and also set the WMShell's geometry */
700 (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
701 (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
704 sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
706 sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
708 sprintf (shell_geom, "=%dx%d", w, h);
712 temp = (char *) xmalloc (1 + strlen (shell_geom));
713 strcpy (temp, shell_geom);
714 FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
719 Xt_SET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp);
722 /* Report to X that a frame property of frame S is being set or changed.
723 If the property is not specially recognized, do nothing.
727 x_set_frame_properties (struct frame *f, Lisp_Object plist)
730 Dimension width = 0, height = 0;
731 Bool width_specified_p = False;
732 Bool height_specified_p = False;
733 Bool x_position_specified_p = False;
734 Bool y_position_specified_p = False;
735 Bool internal_border_width_specified = False;
737 Widget w = FRAME_X_TEXT_WIDGET (f);
739 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
741 Lisp_Object prop = Fcar (tail);
742 Lisp_Object val = Fcar (Fcdr (tail));
748 if (XSTRING_LENGTH (prop) == 0)
751 GET_C_STRING_CTEXT_DATA_ALLOCA (prop, extprop);
754 CONST Extbyte *extval;
757 GET_STRING_CTEXT_DATA_ALLOCA (val, extval, extvallen);
758 XtVaSetValues (w, XtVaTypedArg, extprop,
759 XtRString, extval, extvallen + 1,
763 XtVaSetValues (w, XtVaTypedArg, extprop, XtRInt,
764 XINT (val), sizeof (int),
767 else if (SYMBOLP (prop))
769 Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
770 int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
772 if (NILP (prop) || NILP (str))
774 /* Kludge to handle the font property. */
775 if (EQ (prop, Qfont))
777 /* If the value is not a string we silently ignore it. */
780 Lisp_Object frm, font_spec;
783 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
785 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
786 update_frame_face_values (f);
796 /* Kludge the width/height so that we interpret them in characters
797 instead of pixels. Yuck yuck yuck. */
798 if (!strcmp ((char *) XSTRING_DATA (str), "width"))
802 width_specified_p = True;
805 if (!strcmp ((char *) XSTRING_DATA (str), "height"))
809 height_specified_p = True;
812 /* Further kludge the x/y. */
813 if (!strcmp ((char *) XSTRING_DATA (str), "x"))
816 x = (Position) XINT (val);
817 x_position_specified_p = True;
820 if (!strcmp ((char *) XSTRING_DATA (str), "y"))
823 y = (Position) XINT (val);
824 y_position_specified_p = True;
827 /* Have you figured out by now that this entire function is
828 one gigantic kludge? */
829 if (!strcmp ((char *) XSTRING_DATA (str),
830 "internalBorderWidth"))
832 internal_border_width_specified = True;
838 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val));
840 else if (EQ (val, Qt))
842 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/
844 else if (EQ (val, Qnil))
846 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/
851 XtVaSetValues (w, XtVaTypedArg,
853 (char *) XSTRING_DATA (str),
856 XSTRING_LENGTH (val) + 1,
860 #ifdef HAVE_SCROLLBARS
861 if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth")
862 || !strcmp ((char *) XSTRING_DATA (str),
865 x_update_frame_scrollbars (f);
867 #endif /* HAVE_SCROLLBARS */
871 /* Kludge kludge kludge. We need to deal with the size and position
874 int size_specified_p = width_specified_p || height_specified_p;
875 int position_specified_p = x_position_specified_p ||
876 y_position_specified_p;
878 if (!width_specified_p)
879 width = FRAME_WIDTH (f);
880 if (!height_specified_p)
881 height = FRAME_HEIGHT (f);
883 /* Kludge kludge kludge kludge. */
884 if (position_specified_p &&
885 (!x_position_specified_p || !y_position_specified_p))
888 Widget shell = FRAME_X_SHELL_WIDGET (f);
889 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
890 (x_position_specified_p ? &dummy : &x),
891 (y_position_specified_p ? &dummy : &y));
893 x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
894 y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
898 if (!f->init_finished)
900 int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
901 (position_specified_p ?
902 XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
905 || position_specified_p
906 || internal_border_width_specified)
907 x_set_initial_frame_size (f, flags, x, y, width, height);
911 if (size_specified_p || internal_border_width_specified)
914 XSETFRAME (frame, f);
915 Fset_frame_size (frame, make_int (width),
916 make_int (height), Qnil);
918 if (position_specified_p)
921 XSETFRAME (frame, f);
922 Fset_frame_position (frame, make_int (x), make_int (y));
928 static int frame_title_format_already_set;
931 maybe_set_frame_title_format (Widget shell)
934 /* Only do this if this is the first X frame we're creating.
936 If the *title resource (or -title option) was specified, then
937 set frame-title-format to its value.
940 if (!frame_title_format_already_set)
942 /* No doubt there's a less stupid way to do this. */
944 XtResource resources [2];
945 results [0] = results [1] = 0;
946 resources [0].resource_name = XtNtitle;
947 resources [0].resource_class = XtCTitle;
948 resources [0].resource_type = XtRString;
949 resources [0].resource_size = sizeof (String);
950 resources [0].resource_offset = 0;
951 resources [0].default_type = XtRString;
952 resources [0].default_addr = 0;
953 resources [1].resource_name = XtNiconName;
954 resources [1].resource_class = XtCIconName;
955 resources [1].resource_type = XtRString;
956 resources [1].resource_size = sizeof (String);
957 resources [1].resource_offset = sizeof (char *);
958 resources [1].default_type = XtRString;
959 resources [1].default_addr = 0;
960 XtGetSubresources (XtParent (shell), (XtPointer) results,
962 shell->core.widget_class->core_class.class_name,
963 resources, XtNumber (resources), 0, 0);
965 Vframe_title_format = build_string (results[0]);
967 Vframe_icon_title_format = build_string (results[1]);
970 frame_title_format_already_set = 1;
977 static Widget CurrentDragWidget = NULL;
978 static XtCallbackRec dnd_convert_cb_rec[2];
979 static XtCallbackRec dnd_destroy_cb_rec[2];
980 static int drag_not_done = 0;
983 x_cde_destroy_callback (Widget widget, XtPointer clientData,
986 DtDndDragFinishCallbackStruct *dragFinishInfo =
987 (DtDndDragFinishCallbackStruct *)callData;
988 DtDndContext *dragData = dragFinishInfo->dragData;
992 if (callData != NULL && dragData != NULL)
994 if (dragData->protocol == DtDND_BUFFER_TRANSFER)
996 for (i = 0; i < dragData->numItems; i++)
998 XtFree((char *) dragData->data.buffers[i].bp);
999 if (dragData->data.buffers[i].name)
1000 XtFree(dragData->data.buffers[i].name);
1005 for (i = 0; i < dragData->numItems; i++)
1006 XtFree(dragData->data.files[i]);
1010 /* free the data string */
1013 CurrentDragWidget = NULL;
1017 x_cde_convert_callback (Widget widget, XtPointer clientData,
1020 DtDndConvertCallbackStruct *convertInfo =
1021 (DtDndConvertCallbackStruct *) callData;
1022 char *textdata = (char *) clientData;
1023 char *textptr = NULL;
1026 if (convertInfo == NULL)
1031 if ((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER
1032 && convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER) ||
1033 (convertInfo->reason != DtCR_DND_CONVERT_DATA))
1038 for (textptr=textdata, i=0;
1039 i<convertInfo->dragData->numItems;
1040 textptr+=strlen(textptr)+1, i++)
1042 if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER)
1044 convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr);
1045 convertInfo->dragData->data.buffers[i].size = strlen(textptr);
1046 convertInfo->dragData->data.buffers[i].name = NULL;
1050 convertInfo->dragData->data.files[i] = XtNewString(textptr);
1054 convertInfo->status = DtDND_SUCCESS;
1058 abort_current_drag(Lisp_Object arg)
1060 if (CurrentDragWidget && drag_not_done)
1062 XmDragCancel(CurrentDragWidget);
1063 CurrentDragWidget = NULL;
1068 DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 3, 3, 0, /*
1069 Start a CDE drag from a buffer.
1070 First argument is the event that started the drag (must be a
1071 button-press-event),
1072 second arg defines if the data should be treated as a buffer or
1073 a filename transfer (set to nil for buffer transfer),
1074 and the third argument is a list of data strings.
1075 WARNING: can only handle plain/text and file: transfers!
1077 (event, dragtype, dragdata))
1081 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1083 Widget wid = FRAME_X_TEXT_WIDGET (f);
1084 Display *display = XtDisplayOfObject (wid);
1085 struct device *d = get_device_from_display (display);
1086 struct x_device *xd = DEVICE_X_DATA (d);
1087 XWindowAttributes win_attrib;
1088 unsigned int modifier = 0, state = 0;
1090 int numItems = 0, textlen = 0, pos = 0;
1091 struct Lisp_Event *lisp_event = XEVENT(event);
1092 Lisp_Object item = Qnil;
1093 struct gcpro gcpro1;
1095 /* only drag if this is really a press */
1096 if (EVENT_TYPE(lisp_event) != button_press_event
1097 || !LISTP(dragdata))
1103 * not so cross hack that converts a emacs event back to a XEvent
1106 x_event.xbutton.type = ButtonPress;
1107 x_event.xbutton.send_event = False;
1108 x_event.xbutton.display = XtDisplayOfObject(wid);
1109 x_event.xbutton.window = XtWindowOfObject(wid);
1110 x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0);
1111 x_event.xbutton.subwindow = 0;
1112 x_event.xbutton.time = lisp_event->timestamp;
1113 x_event.xbutton.x = lisp_event->event.button.x;
1114 x_event.xbutton.y = lisp_event->event.button.y;
1115 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1116 x_event.xbutton.window,
1119 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1120 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1124 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1125 x_event.xbutton.y_root = lisp_event->event.button.y;
1127 modifier = lisp_event->event.button.modifiers;
1128 if (modifier & MOD_SHIFT) state |= ShiftMask;
1129 if (modifier & MOD_CONTROL) state |= ControlMask;
1130 if (modifier & MOD_META) state |= xd->MetaMask;
1131 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1132 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1133 if (modifier & MOD_ALT) state |= xd->AltMask;
1134 state |= Button1Mask << (lisp_event->event.button.button-1);
1136 x_event.xbutton.state = state;
1137 x_event.xbutton.button = lisp_event->event.button.button;
1138 x_event.xkey.same_screen = True;
1140 /* convert data strings into a big string */
1142 while (!NILP (item))
1144 if (!STRINGP (XCAR (item)))
1149 textlen += XSTRING_LENGTH (XCAR (item)) + 1;
1157 * concatenate all strings given to one large string, with
1158 * \0 as separator. List is ended by \0.
1160 Ctext = (char *)xmalloc (textlen+1);
1164 while (!NILP (item))
1166 if (!STRINGP (XCAR (item)))
1173 strcpy (Ctext+pos, (CONST char *)XSTRING_DATA (XCAR (item)));
1174 pos += XSTRING_LENGTH (XCAR (item)) + 1;
1179 dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
1180 dnd_convert_cb_rec[0].closure = (XtPointer) Ctext;
1181 dnd_convert_cb_rec[1].callback = NULL;
1182 dnd_convert_cb_rec[1].closure = NULL;
1184 dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
1185 dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext;
1186 dnd_destroy_cb_rec[1].callback = NULL;
1187 dnd_destroy_cb_rec[1].closure = NULL;
1190 DtDndDragStart (wid, &x_event,
1191 (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER),
1201 return numItems?Qt:Qnil;
1208 x_cde_transfer_callback (Widget widget, XtPointer clientData,
1211 char *filePath, *hurl;
1213 Lisp_Object frame = Qnil;
1214 Lisp_Object l_type = Qnil;
1215 Lisp_Object l_data = Qnil;
1216 DtDndTransferCallbackStruct *transferInfo = NULL;
1217 struct gcpro gcpro1, gcpro2, gcpro3;
1220 this needs to be changed to the new protocol:
1221 - we need the button, modifier and pointer states to create a
1222 correct misc_user_event
1223 - the data must be converted to the new format (URL/MIME)
1227 transferInfo = (DtDndTransferCallbackStruct *) callData;
1228 if (transferInfo == NULL)
1231 GCPRO3 (frame, l_type, l_data);
1233 frame = make_frame ((struct frame *) clientData);
1235 if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
1237 l_type = Qdragdrop_URL;
1239 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1241 filePath = transferInfo->dropData->data.files[ii];
1242 hurl = dnd_url_hexify_string ((char *)filePath, "file:");
1243 /* ### Mule-izing required */
1244 l_data = Fcons (make_string ((Bufbyte* )hurl,
1250 else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
1252 int speccount = specpdl_depth();
1254 /* Problem: all buffers a treated as text/plain!!!
1255 Solution: Also support DtDND_TEXT_TRANSFER
1256 perhaps implementation of the Motif protocol
1257 (which is the base of CDE) will clear this */
1258 l_type = Qdragdrop_MIME;
1259 record_unwind_protect(abort_current_drag, Qnil);
1261 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1263 /* let us forget this name thing for now... */
1264 /* filePath = transferInfo->dropData->data.buffers[ii].name;
1265 path = (filePath == NULL) ? Qnil
1266 : make_string ((Bufbyte *)filePath, strlen (filePath)); */
1267 /* what, if the data is no text, and how can I tell it? */
1268 l_data = Fcons ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1269 make_string ((Bufbyte *)"8bit", 4),
1270 make_string ((Bufbyte *)transferInfo->dropData->data.buffers[ii].bp,
1271 transferInfo->dropData->data.buffers[ii].size) ),
1275 unbind_to(speccount, Qnil);
1277 else /* the other cases: NOOP_TRANSFER */
1280 /* The Problem: no button and mods from CDE... */
1282 enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch,
1283 Fcons (l_type, l_data),
1284 0 /* this is the button */,
1285 0 /* these are the mods */,
1292 #endif /* HAVE_CDE */
1294 #ifdef HAVE_OFFIX_DND
1296 DEFUN ("offix-start-drag-internal", Foffix_start_drag_internal, 2, 3, 0, /*
1297 Start a OffiX drag from a buffer.
1298 First arg is the event that started the drag,
1299 second arg should be some string, and the third
1300 is the type of the data (this should be an int).
1301 The type defaults to DndText (4).
1303 (event, data, dtyp))
1307 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1309 Widget wid = FRAME_X_TEXT_WIDGET (f);
1310 Display *display = XtDisplayOfObject (wid);
1311 struct device *d = get_device_from_display (display);
1312 struct x_device *xd = DEVICE_X_DATA (d);
1313 XWindowAttributes win_attrib;
1314 unsigned int modifier = 0, state = 0;
1315 char *dnd_data = NULL;
1316 unsigned long dnd_len = 0;
1317 int dnd_typ = DndText, dnd_dealloc = 0;
1318 struct Lisp_Event *lisp_event = XEVENT(event);
1320 /* only drag if this is really a press */
1321 if (EVENT_TYPE(lisp_event) != button_press_event)
1324 /* get the desired type */
1325 if (!NILP (dtyp) && INTP (dtyp))
1326 dnd_typ = XINT (dtyp);
1328 if (dnd_typ == DndFiles)
1330 Lisp_Object run = data;
1333 if (NILP ( Flistp (data)))
1336 /* construct the data from a list of files */
1338 dnd_data = (char *) xmalloc (1);
1342 if (!STRINGP (XCAR (run)))
1347 len = XSTRING_LENGTH (XCAR (run)) + 1;
1348 dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
1349 strcpy (dnd_data + dnd_len - 1, (CONST char *)XSTRING_DATA (XCAR (run)));
1354 dnd_data[dnd_len - 1] = 0; /* the list-ending zero */
1360 if (!STRINGP (data))
1363 /* and what's with MULE data ??? */
1364 dnd_data = (char *)XSTRING_DATA (data);
1365 dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */
1369 /* not so gross hack that converts an emacs event back to a XEvent */
1371 x_event.xbutton.type = ButtonPress;
1372 x_event.xbutton.send_event = False;
1373 x_event.xbutton.display = XtDisplayOfObject(wid);
1374 x_event.xbutton.window = XtWindowOfObject(wid);
1375 x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0);
1376 x_event.xbutton.subwindow = 0;
1377 x_event.xbutton.time = lisp_event->timestamp;
1378 x_event.xbutton.x = lisp_event->event.button.x;
1379 x_event.xbutton.y = lisp_event->event.button.y;
1380 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1381 x_event.xbutton.window,
1384 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1385 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1389 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1390 x_event.xbutton.y_root = lisp_event->event.button.y;
1393 modifier = lisp_event->event.button.modifiers;
1394 if (modifier & MOD_SHIFT) state |= ShiftMask;
1395 if (modifier & MOD_CONTROL) state |= ControlMask;
1396 if (modifier & MOD_META) state |= xd->MetaMask;
1397 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1398 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1399 if (modifier & MOD_ALT) state |= xd->AltMask;
1400 state |= Button1Mask << (lisp_event->event.button.button-1);
1402 x_event.xbutton.state = state;
1403 x_event.xbutton.button = lisp_event->event.button.button;
1404 x_event.xkey.same_screen = True;
1406 DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len);
1410 /* the next thing blocks everything... */
1411 if (DndHandleDragging(wid, &x_event))
1417 #endif /* HAVE_OFFIX_DND */
1420 /************************************************************************/
1421 /* widget creation */
1422 /************************************************************************/
1424 /* The widget hierarchy is
1426 argv[0] shell container FRAME-NAME
1427 ApplicationShell EmacsShell EmacsManager EmacsFrame
1429 We accept geometry specs in this order:
1431 *FRAME-NAME.geometry
1432 *EmacsFrame.geometry
1435 Other possibilities for widget hierarchies might be
1437 argv[0] frame container FRAME-NAME
1438 ApplicationShell EmacsShell EmacsManager EmacsFrame
1440 argv[0] FRAME-NAME container FRAME-NAME
1441 ApplicationShell EmacsShell EmacsManager EmacsFrame
1443 argv[0] FRAME-NAME container emacsTextPane
1444 ApplicationShell EmacsShell EmacsManager EmacsFrame
1446 #ifdef EXTERNAL_WIDGET
1447 The ExternalShell widget is simply a replacement for the Shell widget
1448 which is able to deal with using an externally-supplied window instead
1449 of always creating its own.
1454 #ifdef EXTERNAL_WIDGET
1457 is_valid_window (Window w, struct device *d)
1459 XWindowAttributes xwa;
1460 Display *dpy = DEVICE_X_DISPLAY (d);
1462 expect_x_error (dpy);
1463 XGetWindowAttributes (dpy, w, &xwa);
1464 return !x_error_occurred_p (dpy);
1467 #endif /* EXTERNAL_WIDGET */
1469 /* This sends a synthetic mouse-motion event to the frame, if the mouse
1470 is over the frame. This ensures that the cursor gets set properly
1471 before the user moves the mouse for the first time. */
1474 x_send_synthetic_mouse_event (struct frame *f)
1476 /* #### write this function. */
1480 first_x_frame_p (struct frame *f)
1482 Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
1483 while (!NILP (rest) &&
1484 (f == XFRAME (XCAR (rest)) ||
1485 !FRAME_X_P (XFRAME (XCAR (rest)))))
1490 /* Figure out what size the EmacsFrame widget should initially be,
1491 and set it. Should be called after the default font has been
1492 determined but before the widget has been realized. */
1495 x_initialize_frame_size (struct frame *f)
1497 /* Geometry of the AppShell */
1501 unsigned int app_w = 0;
1502 unsigned int app_h = 0;
1504 /* Geometry of the EmacsFrame */
1505 int frame_flags = 0;
1508 unsigned int frame_w = 0;
1509 unsigned int frame_h = 0;
1511 /* Hairily merged geometry */
1514 unsigned int w = 80;
1515 unsigned int h = 40;
1518 char *geom = 0, *ew_geom = 0;
1519 Boolean iconic_p = False, ew_iconic_p = False;
1521 Widget wmshell = FRAME_X_SHELL_WIDGET (f);
1522 /* #### This may not be an ApplicationShell any more, with the 'popup
1524 Widget app_shell = XtParent (wmshell);
1525 Widget ew = FRAME_X_TEXT_WIDGET (f);
1527 /* set the position of the frame's root window now. When the
1528 frame was created, the position was initialized to (0,0). */
1530 struct window *win = XWINDOW (f->root_window);
1532 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1533 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
1535 if (!NILP (f->minibuffer_window))
1537 win = XWINDOW (f->minibuffer_window);
1538 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1542 #ifdef EXTERNAL_WIDGET
1543 /* If we're an external widget, then the size of the frame is predetermined
1544 (by the client) and is not our decision to make. */
1545 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1550 /* #### this junk has not been tested; therefore it's
1551 probably wrong. Doesn't really matter at this point because
1552 currently all frames are either top-level or external widgets. */
1554 /* If we're not our own top-level window, then we shouldn't go messing around
1555 with top-level shells or "Emacs.geometry" or any such stuff. Therefore,
1556 we do as follows to determine the size of the frame:
1558 1) If a value for the frame's "geometry" resource was specified, then
1559 use it. (This specifies a size in characters.)
1560 2) Else, if the "width" and "height" resources were specified, then
1561 leave them alone. (This is a value in pixels. Sorry, we can't break
1562 Xt conventions here.)
1563 3) Else, assume a size of 64x12. (This is somewhat arbitrary, but
1564 it's unlikely that a size of 80x40 is desirable because we're probably
1565 inside of a dialog box.)
1567 Set the widget's x, y, height, and width as determined. Don't set the
1568 top-level container widget, because we don't necessarily know what it
1569 is. (Assume it is smart and pays attention to our values.)
1572 if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
1574 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1576 frame_flags = XParseGeometry (ew_geom,
1578 &frame_w, &frame_h);
1579 if (! (frame_flags & (WidthValue | HeightValue)))
1582 XtSetArg (al [0], XtNwidth, &frame_w);
1583 XtSetArg (al [1], XtNheight, &frame_h);
1584 XtGetValues (ew, al, 2);
1585 if (!frame_w && !frame_h)
1589 frame_flags |= WidthValue | HeightValue;
1592 if (frame_flags & (WidthValue | HeightValue))
1593 EmacsFrameSetCharSize (ew, frame_w, frame_h);
1594 if (frame_flags & (XValue | YValue))
1597 XtSetArg (al [0], XtNwidth, &frame_w);
1598 XtSetArg (al [1], XtNheight, &frame_h);
1599 XtGetValues (ew, al, 2);
1601 if (frame_flags & XNegative)
1603 if (frame_flags & YNegative)
1606 XtSetArg (al [0], XtNx, frame_x);
1607 XtSetArg (al [1], XtNy, frame_y);
1608 XtSetValues (ew, al, 2);
1614 /* OK, we're a top-level shell. */
1616 if (!XtIsWMShell (wmshell))
1619 /* If the EmacsFrame doesn't have a geometry but the shell does,
1620 treat that as the geometry of the frame.
1621 (Is this bogus? I'm not sure.) */
1623 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1626 Xt_GET_VALUE (wmshell, XtNgeometry, &geom);
1630 Xt_SET_VALUE (ew, XtNgeometry, ew_geom);
1634 /* If the Shell is iconic, then the EmacsFrame is iconic.
1635 (Is this bogus? I'm not sure.) */
1636 Xt_GET_VALUE (ew, XtNiconic, &ew_iconic_p);
1639 Xt_GET_VALUE (wmshell, XtNiconic, &iconic_p);
1642 ew_iconic_p = iconic_p;
1643 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1647 Xt_GET_VALUE (app_shell, XtNgeometry, &geom);
1649 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
1652 frame_flags = XParseGeometry (ew_geom,
1654 &frame_w, &frame_h);
1656 if (first_x_frame_p (f))
1658 /* If this is the first frame created:
1659 ====================================
1661 - Use the ApplicationShell's size/position, if specified.
1662 (This is "Emacs.geometry", or the "-geometry" command line arg.)
1663 - Else use the EmacsFrame's size/position.
1664 (This is "*FRAME-NAME.geometry")
1666 - If the AppShell is iconic, the frame should be iconic.
1668 AppShell comes first so that -geometry always applies to the first
1669 frame created, even if there is an "every frame" entry in the
1672 if (app_flags & (XValue | YValue))
1674 x = app_x; y = app_y;
1675 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
1677 else if (frame_flags & (XValue | YValue))
1679 x = frame_x; y = frame_y;
1680 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1683 if (app_flags & (WidthValue | HeightValue))
1685 w = app_w; h = app_h;
1686 flags |= (app_flags & (WidthValue | HeightValue));
1688 else if (frame_flags & (WidthValue | HeightValue))
1690 w = frame_w; h = frame_h;
1691 flags |= (frame_flags & (WidthValue | HeightValue));
1694 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
1697 Xt_GET_VALUE (app_shell, XtNiconic, &iconic_p);
1700 ew_iconic_p = iconic_p;
1701 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1707 /* If this is not the first frame created:
1708 ========================================
1710 - use the EmacsFrame's size/position if specified
1711 - Otherwise, use the ApplicationShell's size, but not position.
1713 So that means that one can specify the position of the first frame
1714 with "Emacs.geometry" or `-geometry'; but can only specify the
1715 position of subsequent frames with "*FRAME-NAME.geometry".
1717 AppShell comes second so that -geometry does not apply to subsequent
1718 frames when there is an "every frame" entry in the resource db,
1719 but does apply to the first frame.
1721 if (frame_flags & (XValue | YValue))
1723 x = frame_x; y = frame_y;
1724 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1727 if (frame_flags & (WidthValue | HeightValue))
1729 w = frame_w; h = frame_h;
1730 flags |= (frame_flags & (WidthValue | HeightValue));
1732 else if (app_flags & (WidthValue | HeightValue))
1736 flags |= (app_flags & (WidthValue | HeightValue));
1740 x_set_initial_frame_size (f, flags, x, y, w, h);
1744 x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
1748 /* compute height of all top-area widgets */
1749 for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1751 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1752 if (wid && XtIsManaged (wid))
1753 *topbreadth += wid->core.height + 2*wid->core.border_width;
1758 x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
1760 struct frame *f = (struct frame *) client_data;
1761 EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
1762 Dimension width = emst->width;
1763 Dimension height = emst->height;
1764 Widget text = FRAME_X_TEXT_WIDGET (f);
1765 Dimension textbord = text->core.border_width;
1766 Dimension topbreadth;
1767 Position text_x = 0, text_y = 0;
1770 x_get_layout_sizes (f, &topbreadth);
1772 /* first the menubar and psheets ... */
1773 for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1775 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1776 if (wid && XtIsManaged (wid))
1778 Dimension bord = wid->core.border_width;
1779 XtConfigureWidget (wid, 0, text_y,
1780 width - 2*bord, wid->core.height,
1782 text_y += wid->core.height + 2*bord;
1786 #ifdef HAVE_SCROLLBARS
1787 f->scrollbar_y_offset = topbreadth + textbord;
1790 /* finally the text area */
1791 XtConfigureWidget (text, text_x, text_y,
1793 height - text_y - 2*textbord,
1798 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1800 struct frame *f = (struct frame *) client_data;
1801 EmacsManagerQueryGeometryStruct *emst =
1802 (EmacsManagerQueryGeometryStruct *) call_data;
1803 Widget text = FRAME_X_TEXT_WIDGET (f);
1804 Dimension textbord = text->core.border_width;
1805 Dimension topbreadth;
1806 XtWidgetGeometry req, repl;
1807 int mask = emst->request_mode & (CWWidth | CWHeight);
1809 x_get_layout_sizes (f, &topbreadth);
1811 /* Strip away menubar from suggested size, and ask the text widget
1812 what size it wants to be. */
1813 req.request_mode = mask;
1815 req.width = emst->proposed_width - 2*textbord;
1816 if (mask & CWHeight)
1817 req.height = emst->proposed_height - topbreadth - 2*textbord;
1818 XtQueryGeometry (text, &req, &repl);
1820 /* Now add the menubar back again */
1821 emst->proposed_width = repl.width + 2*textbord;
1822 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1825 /* Creates the widgets for a frame.
1826 lisp_window_id is a Lisp description of an X window or Xt
1829 This function does not create or map the windows. (That is
1830 done by x_popup_frame().)
1833 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1836 struct device *d = XDEVICE (f->device);
1837 Visual *visual = DEVICE_X_VISUAL (d);
1838 int depth = DEVICE_X_DEPTH (d);
1839 Colormap cmap = DEVICE_X_COLORMAP (d);
1840 #ifdef EXTERNAL_WIDGET
1841 Window window_id = 0;
1846 Widget text, container, shell;
1847 Widget parentwid = 0;
1848 #ifdef HAVE_MENUBARS
1849 int menubar_visible;
1853 if (STRINGP (f->name))
1854 GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, name);
1858 /* The widget hierarchy is
1860 argv[0] shell pane FRAME-NAME
1861 ApplicationShell EmacsShell EmacsManager EmacsFrame
1863 (the type of the shell is ExternalShell if this frame is running
1864 in another client's window)
1866 However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
1867 Normally such shells have name/class shellname/appclass, which in this
1868 case would be "shell/Emacs" instead of "frame-name/Emacs". We could
1869 also get around this by naming the shell "frame-name", but that would
1870 be confusing because the text area (the EmacsFrame widget inferior of
1871 the shell) is also called that. So we just set the WM_CLASS property.
1874 #ifndef EXTERNAL_WIDGET
1875 if (!NILP (lisp_window_id))
1876 error ("support for external widgets was not enabled at compile-time");
1878 if (!NILP (lisp_window_id))
1882 CHECK_STRING (lisp_window_id);
1883 string = (char *) (XSTRING_DATA (lisp_window_id));
1884 if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
1885 sscanf (string+2, "%lxu", &window_id);
1887 else if (string[0] == 'w')
1889 sscanf (string+1, "%x", &parent_widget);
1891 window_id = XtWindow (parent_widget);
1895 sscanf (string, "%lu", &window_id);
1896 if (!is_valid_window (window_id, d))
1897 error ("Invalid window %lu", (unsigned long) window_id);
1898 FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
1900 #endif /* EXTERNAL_WIDGET */
1901 FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
1904 XtSetArg (al[ac], XtNallowShellResize, True); ac++;
1905 #ifdef LWLIB_USES_MOTIF
1906 /* Motif sucks beans. Without this in here, it will delete the window
1907 out from under us when it receives a WM_DESTROY_WINDOW message
1909 XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1912 #ifdef EXTERNAL_WIDGET
1915 XtSetArg (al[ac], XtNwindow, window_id); ac++;
1918 #endif /* EXTERNAL_WIDGET */
1920 XtSetArg (al[ac], XtNinput, True); ac++;
1921 XtSetArg (al[ac], XtNminWidthCells, 10); ac++;
1922 XtSetArg (al[ac], XtNminHeightCells, 1); ac++;
1923 XtSetArg (al[ac], XtNvisual, visual); ac++;
1924 XtSetArg (al[ac], XtNdepth, depth); ac++;
1925 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1930 parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
1931 XtSetArg (al[ac], XtNtransientFor, parentwid); ac++;
1934 shell = XtCreatePopupShell ("shell",
1936 #ifdef EXTERNAL_WIDGET
1937 window_id ? externalShellWidgetClass :
1939 parentwid ? transientEmacsShellWidgetClass :
1940 topLevelEmacsShellWidgetClass
1942 parentwid ? parentwid :
1943 DEVICE_XT_APP_SHELL (d),
1945 FRAME_X_SHELL_WIDGET (f) = shell;
1946 maybe_set_frame_title_format (shell);
1948 /* Create the manager widget */
1950 XtSetArg (al[ac], XtNvisual, visual); ac++;
1951 XtSetArg (al[ac], XtNdepth, depth); ac++;
1952 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1954 container = XtCreateWidget ("container",
1955 emacsManagerWidgetClass, shell, al, ac);
1956 FRAME_X_CONTAINER_WIDGET (f) = container;
1957 XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
1959 XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
1962 /* Create the text area */
1964 XtSetArg (al[ac], XtNvisual, visual); ac++;
1965 XtSetArg (al[ac], XtNdepth, depth); ac++;
1966 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1967 XtSetArg (al[ac], XtNborderWidth, 0); ac++; /* should this be settable? */
1968 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
1969 text = XtCreateWidget (name, emacsFrameClass, container, al, ac);
1970 FRAME_X_TEXT_WIDGET (f) = text;
1972 #ifdef HAVE_MENUBARS
1973 /* Create the initial menubar widget. */
1974 menubar_visible = x_initialize_frame_menubar (f);
1975 FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
1976 FRAME_X_NUM_TOP_WIDGETS (f) = 1;
1978 if (menubar_visible)
1979 XtManageChild (menubar);
1980 #endif /* HAVE_MENUBARS */
1981 XtManageChild (text);
1982 XtManageChild (container);
1985 /* We used to call XtPopup() in x_popup_frame, but that doesn't give
1986 you control over whether the widget is initially mapped or not
1987 because XtPopup() makes an unconditional call to XMapRaised().
1988 Boy, those Xt designers were clever.
1990 When we first removed it we only kept the XtRealizeWidget call in
1991 XtPopup. For everything except HP's that was enough. For HP's,
1992 though, the failure to call the popup callbacks resulted in XEmacs
1993 not accepting any input. Bizarre but true. Stupid but true.
1995 So, in case there are any other gotchas floating out there along
1996 the same lines I've duplicated the majority of XtPopup here. It
1997 assumes no grabs and that the widget is not already popped up, both
1998 valid assumptions for the one place this is called from. */
2000 xemacs_XtPopup (Widget widget)
2002 ShellWidget shell_widget = (ShellWidget) widget;
2003 XtGrabKind call_data = XtGrabNone;
2005 XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data);
2007 shell_widget->shell.popped_up = TRUE;
2008 shell_widget->shell.grab_kind = XtGrabNone;
2009 shell_widget->shell.spring_loaded = False;
2011 if (shell_widget->shell.create_popup_child_proc != NULL)
2012 (*(shell_widget->shell.create_popup_child_proc))(widget);
2014 /* The XtSetValues below are not in XtPopup menu. We just want to
2015 make absolutely sure... */
2016 Xt_SET_VALUE (widget, XtNmappedWhenManaged, False);
2017 XtRealizeWidget (widget);
2018 Xt_SET_VALUE (widget, XtNmappedWhenManaged, True);
2021 /* create the windows for the specified frame and display them.
2022 Note that the widgets have already been created, and any
2023 necessary geometry calculations have already been done. */
2025 x_popup_frame (struct frame *f)
2027 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
2028 Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
2029 struct device *d = XDEVICE (FRAME_DEVICE (f));
2031 /* Before mapping the window, make sure that the WMShell's notion of
2032 whether it should be iconified is synchronized with the EmacsFrame's
2035 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2036 x_wm_set_shell_iconic_p (shell_widget,
2037 ((EmacsFrame) frame_widget)
2038 ->emacs_frame.iconic);
2040 xemacs_XtPopup (shell_widget);
2042 if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
2043 XtMapWidget (shell_widget);
2046 /* We may have set f->visible to 1 in x_init_frame(), so undo
2048 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
2052 #ifdef EXTERNAL_WIDGET
2053 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2054 ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
2057 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2059 /* tell the window manager about us. */
2060 x_wm_store_class_hints (shell_widget, XtName (frame_widget));
2062 #ifndef HAVE_SESSION
2063 x_wm_maybe_store_wm_command (f);
2064 #endif /* HAVE_SESSION */
2066 x_wm_hack_wm_protocols (shell_widget);
2071 #endif /* HAVE_XIM */
2074 /* Allow XEmacs to respond to EditRes requests. See the O'Reilly Xt */
2075 /* Intrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
2077 XtAddEventHandler (shell_widget, /* the shell widget in question */
2078 (EventMask) NoEventMask,/* OR with existing mask */
2079 True, /* called on non-maskable events? */
2080 (XtEventHandler) _XEditResCheckMessages, /* the handler */
2082 #endif /* HACK_EDITRES */
2086 XtCallbackRec dnd_transfer_cb_rec[2];
2088 dnd_transfer_cb_rec[0].callback = x_cde_transfer_callback;
2089 dnd_transfer_cb_rec[0].closure = (XtPointer) f;
2090 dnd_transfer_cb_rec[1].callback = NULL;
2091 dnd_transfer_cb_rec[1].closure = NULL;
2093 DtDndVaDropRegister (FRAME_X_TEXT_WIDGET (f),
2094 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
2095 XmDROP_COPY, dnd_transfer_cb_rec,
2096 DtNtextIsBuffer, True,
2097 DtNregisterChildren, True,
2098 DtNpreserveRegistration, False,
2101 #endif /* HAVE_CDE */
2103 /* Do a stupid property change to force the server to generate a
2104 propertyNotify event so that the event_stream server timestamp will
2105 be initialized to something relevant to the time we created the window.
2107 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2108 DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
2109 (unsigned char*) NULL, 0);
2111 x_send_synthetic_mouse_event (f);
2115 allocate_x_frame_struct (struct frame *f)
2117 /* zero out all slots. */
2118 f->frame_data = xnew_and_zero (struct x_frame);
2120 /* yeah, except the lisp ones */
2121 FRAME_X_ICON_PIXMAP (f) = Qnil;
2122 FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
2126 /************************************************************************/
2127 /* Lisp functions */
2128 /************************************************************************/
2131 x_init_frame_1 (struct frame *f, Lisp_Object props)
2133 /* This function can GC */
2134 Lisp_Object device = FRAME_DEVICE (f);
2135 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
2136 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
2141 popup = Fselected_frame (device);
2142 CHECK_LIVE_FRAME (popup);
2143 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
2144 signal_simple_error_2 ("Parent must be on same device as frame",
2149 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
2150 * to make sure that messages were displayed as soon as possible
2151 * if we're creating the first frame on a device. But it is
2152 * better to just set this all the time, so that when a new frame
2153 * is created that covers the selected frame, echo area status
2154 * messages can still be seen. f->visible is reset later if the
2155 * initially-unmapped property is found to be non-nil in the
2160 allocate_x_frame_struct (f);
2161 x_create_widgets (f, lisp_window_id, popup);
2165 x_init_frame_2 (struct frame *f, Lisp_Object props)
2167 /* Set up the values of the widget/frame. A case could be made for putting
2168 this inside of the widget's initialize method. */
2170 update_frame_face_values (f);
2171 x_initialize_frame_size (f);
2173 * update_frame_title() can't be done here, because some of the
2174 * modeline specs depend on the frame's device having a selected
2175 * frame, and that may not have been set up yet. The redisplay
2176 * will update the frame title anyway, so nothing is lost.
2178 * It turns out it gives problems with FVWMs name based mapping.
2179 * We'll just need to be careful in the modeline specs.
2181 update_frame_title (f);
2185 x_init_frame_3 (struct frame *f)
2187 /* Pop up the frame. */
2193 x_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
2195 markobj (FRAME_X_ICON_PIXMAP (f));
2196 markobj (FRAME_X_ICON_PIXMAP_MASK (f));
2200 x_set_frame_icon (struct frame *f)
2202 Pixmap x_pixmap, x_mask;
2204 if (IMAGE_INSTANCEP (f->icon)
2205 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
2207 x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (f->icon);
2208 x_mask = XIMAGE_INSTANCE_X_MASK (f->icon);
2216 /* Store the X data into the widget. */
2219 XtSetArg (al [0], XtNiconPixmap, x_pixmap);
2220 XtSetArg (al [1], XtNiconMask, x_mask);
2221 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
2226 x_set_frame_pointer (struct frame *f)
2228 XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
2229 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2230 XIMAGE_INSTANCE_X_CURSOR (f->pointer));
2231 XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
2235 x_get_frame_parent (struct frame *f)
2237 Widget parentwid = 0;
2239 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNtransientFor, &parentwid);
2240 /* find the frame whose wid is parentwid */
2243 Lisp_Object frmcons;
2244 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
2246 Lisp_Object frame = XCAR (frmcons);
2247 if (FRAME_X_SHELL_WIDGET (XFRAME (frame)) == parentwid)
2254 DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
2255 Get the ID of the X11 window.
2256 This gives us a chance to manipulate the Emacs window from within a
2257 different program. Since the ID is an unsigned long, we return it as
2263 struct frame *f = decode_x_frame (frame);
2265 sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
2266 return build_string (str);
2270 /************************************************************************/
2271 /* manipulating the X window */
2272 /************************************************************************/
2275 x_set_frame_position (struct frame *f, int xoff, int yoff)
2277 Widget w = FRAME_X_SHELL_WIDGET (f);
2278 Display *dpy = XtDisplay (w);
2279 Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
2280 Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
2281 Dimension shell_w, shell_h, shell_bord;
2285 XtSetArg (al [0], XtNwidth, &shell_w);
2286 XtSetArg (al [1], XtNheight, &shell_h);
2287 XtSetArg (al [2], XtNborderWidth, &shell_bord);
2288 XtGetValues (w, al, 3);
2291 xoff >= 0 && yoff >= 0 ? NorthWestGravity :
2292 xoff >= 0 ? SouthWestGravity :
2293 yoff >= 0 ? NorthEastGravity :
2296 xoff += frame_w - shell_w - 2*shell_bord;
2298 yoff += frame_h - shell_h - 2*shell_bord;
2300 /* Update the hints so that, if this window is currently iconified, it will
2301 come back at the right place. We can't look at s->visible to determine
2302 whether it is iconified because it might not be up-to-date yet (the queue
2303 might not be processed). */
2304 XtSetArg (al [0], XtNwinGravity, win_gravity);
2305 XtSetArg (al [1], XtNx, xoff);
2306 XtSetArg (al [2], XtNy, yoff);
2307 XtSetValues (w, al, 3);
2309 /* Sometimes you will find that
2311 (set-frame-position (selected-frame) -50 -50)
2313 doesn't put the frame where you expect it to: i.e. it's closer to
2314 the lower-right corner than it should be, and it appears that the
2315 size of the WM decorations was not taken into account. This is
2316 *not* a problem with this function. Both mwm and twm have bugs
2317 in handling this situation. (mwm ignores the window gravity and
2318 always assumes NorthWest, except the first time you map the
2319 window; twm gets things almost right, but forgets to account for
2320 the border width of the top-level window.) This function does
2321 what it's supposed to according to the ICCCM, and I'm not about
2322 to hack around window-manager bugs. */
2325 /* This is not necessary under either mwm or twm */
2326 x_wm_mark_shell_position_user_specified (w);
2330 /* Call this to change the size of frame S's x-window. */
2333 x_set_frame_size (struct frame *f, int cols, int rows)
2335 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
2337 /* this is not correct. x_set_frame_size() is called from
2338 Fset_frame_size(), which may or may not have been called
2339 by the user (e.g. update_EmacsFrame() calls it when the font
2340 changes). For now, don't bother with getting this right. */
2341 x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
2346 x_set_mouse_position (struct window *w, int x, int y)
2348 struct frame *f = XFRAME (w->frame);
2350 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2351 XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
2352 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
2356 x_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
2358 Display *display = DEVICE_X_DISPLAY (d);
2359 Window child_window;
2364 unsigned int keys_and_buttons;
2367 if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
2368 &root_window, &child_window, &root_x, &root_y,
2369 &win_x, &win_y, &keys_and_buttons) == False)
2372 if (child_window == None)
2373 return 0; /* not over any window. */
2378 if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
2379 &win_x, &win_y, &child_window) == False)
2383 if (child_window == None)
2387 /* At this point, win is the innermost window containing the pointer
2388 and win_x and win_y are the coordinates of that window. */
2389 f = x_any_window_to_frame (d, win);
2392 XSETFRAME (*frame, f);
2394 if (XTranslateCoordinates (display, win,
2395 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2396 win_x, win_y, x, y, &child_window) == False)
2404 x_cant_notify_wm_error (void)
2406 error ("Can't notify window manager of iconification.");
2409 /* Raise frame F. */
2411 x_raise_frame_1 (struct frame *f, int force)
2413 if (FRAME_VISIBLE_P (f) || force)
2415 Widget bottom_dialog;
2418 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2419 Window emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
2421 /* first raises all the dialog boxes, then put emacs just below the
2422 * bottom most dialog box */
2423 bottom_dialog = lw_raise_all_pop_up_widgets ();
2424 if (bottom_dialog && XtWindow (bottom_dialog))
2426 xwc.sibling = XtWindow (bottom_dialog);
2427 xwc.stack_mode = Below;
2428 flags = CWSibling | CWStackMode;
2432 xwc.stack_mode = Above;
2433 flags = CWStackMode;
2436 if (!XReconfigureWMWindow (display, emacs_window,
2437 DefaultScreen (display),
2439 x_cant_notify_wm_error ();
2444 x_raise_frame (struct frame *f)
2446 x_raise_frame_1 (f, 1);
2449 /* Lower frame F. */
2451 x_lower_frame (struct frame *f)
2453 if (FRAME_VISIBLE_P (f))
2455 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2457 unsigned int flags = CWStackMode;
2459 xwc.stack_mode = Below;
2460 if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
2461 DefaultScreen (display), flags, &xwc))
2462 x_cant_notify_wm_error ();
2466 /* Change from withdrawn state to mapped state. */
2468 x_make_frame_visible (struct frame *f)
2470 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2472 if (!FRAME_VISIBLE_P(f))
2473 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2475 x_raise_frame_1 (f, 0);
2478 /* Change from mapped state to withdrawn state. */
2480 x_make_frame_invisible (struct frame *f)
2482 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2484 if (!FRAME_VISIBLE_P(f))
2487 if (!XWithdrawWindow (display,
2488 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2489 DefaultScreen (display)))
2490 x_cant_notify_wm_error ();
2494 x_frame_visible_p (struct frame *f)
2497 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2498 XWindowAttributes xwa;
2502 This is bad, very bad :-(
2503 It is not compatible with our tristate visible and
2504 it should never ever change the visibility for us, this leads to
2505 the frame-freeze problem under fvwm because with the pager
2507 Mappedness != Viewability != Visibility != Emacs f->visible
2509 This first unequalness is the reason for the frame freezing problem
2510 under fvwm (it happens when the frame is another fvwm-page)
2512 The second unequalness happen when it is on the same fvwm-page
2513 but in an invisible part of the visible screen.
2515 For now we just return the XEmacs internal value --- which might not be up
2516 to date. Is that a problem? ---. Otherwise we should
2517 use async visibility like in standard Emacs.
2520 if (!XGetWindowAttributes (display,
2521 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2525 result = xwa.map_state == IsViewable;
2526 /* In this implementation it should at least be != IsUnmapped
2529 f->visible = result;
2537 x_frame_totally_visible_p (struct frame *f)
2539 return FRAME_X_TOTALLY_VISIBLE_P (f);
2542 /* Change window state from mapped to iconified. */
2544 x_iconify_frame (struct frame *f)
2546 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2548 if (!XIconifyWindow (display,
2549 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2550 DefaultScreen (display)))
2551 x_cant_notify_wm_error ();
2556 /* Sets the X focus to frame f. */
2558 x_focus_on_frame (struct frame *f)
2560 XWindowAttributes xwa;
2561 Widget shell_widget;
2564 assert (FRAME_X_P (f));
2566 shell_widget = FRAME_X_SHELL_WIDGET (f);
2567 if (!XtWindow (shell_widget))
2570 #ifdef EXTERNAL_WIDGET
2571 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2572 ExternalShellSetFocus (shell_widget);
2573 #endif /* EXTERNAL_WIDGET */
2575 /* Do the ICCCM focus change if the window is still visible.
2576 The s->visible flag might not be up-to-date, because we might
2577 not have processed magic events recently. So make a server
2578 round-trip to find out whether it's really mapped right now.
2579 We grab the server to do this, because that's the only way to
2580 eliminate the race condition.
2582 XGrabServer (XtDisplay (shell_widget));
2583 if (XGetWindowAttributes (XtDisplay (shell_widget),
2584 XtWindow (shell_widget),
2586 /* JV: it is bad to change the visibility like this, so we don't for the
2587 moment, at least change_frame_visibility should be called
2588 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2589 but still X-invisible
2590 f->visible = xwa.map_state == IsViewable; */
2591 viewable = xwa.map_state == IsViewable;
2598 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2599 /* Don't explicitly set the focus on this window unless the focus
2600 was on some other window (not PointerRoot). Note that, even when
2601 running a point-to-type window manager like *twm, there is always
2602 a focus window; the window manager maintains that based on the
2603 mouse position. If you set the "NoTitleFocus" option in these
2604 window managers, then the server itself maintains the focus via
2605 PointerRoot, and changing that to focus on the window would make
2606 the window grab the focus. Very bad.
2608 if (focus != PointerRoot)
2610 XSetInputFocus (XtDisplay (shell_widget),
2611 XtWindow (shell_widget),
2613 DEVICE_X_MOUSE_TIMESTAMP
2614 (XDEVICE (FRAME_DEVICE (f))));
2615 XFlush (XtDisplay (shell_widget));
2618 XUngrabServer (XtDisplay (shell_widget));
2619 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2622 /* Destroy the X window of frame S. */
2624 x_delete_frame (struct frame *f)
2626 #ifndef HAVE_SESSION
2627 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2628 x_wm_maybe_move_wm_command (f);
2629 #endif /* HAVE_SESSION */
2632 DtDndDropUnregister (FRAME_X_TEXT_WIDGET (f));
2633 #endif /* HAVE_CDE */
2635 assert (FRAME_X_SHELL_WIDGET (f));
2636 if (FRAME_X_SHELL_WIDGET (f))
2638 Display *dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
2639 expect_x_error (dpy);
2640 /* for obscure reasons having (I think) to do with the internal
2641 window-to-widget hierarchy maintained by Xt, we have to call
2642 XtUnrealizeWidget() here. Xt can really suck. */
2643 if (f->being_deleted)
2644 XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
2645 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2646 x_error_occurred_p (dpy);
2648 /* make sure the windows are really gone! */
2649 /* ### Is this REALLY necessary? */
2652 FRAME_X_SHELL_WIDGET (f) = 0;
2655 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2657 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2658 FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0;
2663 xfree (f->frame_data);
2669 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2675 XSETFRAME(frame, frm);
2677 if (EQ (name, Qforeground))
2679 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2682 if (!EQ (color, Vthe_null_color_instance))
2684 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2685 XtSetArg (al[ac], XtNforeground, (void *) fgc.pixel); ac++;
2688 else if (EQ (name, Qbackground))
2690 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2693 if (!EQ (color, Vthe_null_color_instance))
2695 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2696 XtSetArg (al[ac], XtNbackground, (void *) bgc.pixel); ac++;
2699 /* Really crappy way to force the modeline shadows to be
2700 redrawn. But effective. */
2701 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2702 MARK_FRAME_CHANGED (frm);
2704 else if (EQ (name, Qfont))
2706 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2708 if (!EQ (font, Vthe_null_font_instance))
2709 XtSetArg (al[ac], XtNfont,
2710 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2716 XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
2718 #ifdef HAVE_TOOLBARS
2719 /* Setting the background clears the entire frame area
2720 including the toolbar so we force an immediate redraw of
2722 if (EQ (name, Qbackground))
2723 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2724 #endif /* HAVE_TOOLBARS */
2726 /* Set window manager resize increment hints according to
2727 the new character size */
2728 if (EQ (name, Qfont))
2729 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2733 /************************************************************************/
2734 /* initialization */
2735 /************************************************************************/
2738 syms_of_frame_x (void)
2740 defsymbol (&Qwindow_id, "window-id");
2741 defsymbol (&Qx_resource_name, "x-resource-name");
2743 DEFSUBR (Fx_window_id);
2745 DEFSUBR (Fcde_start_drag_internal);
2747 #ifdef HAVE_OFFIX_DND
2748 DEFSUBR (Foffix_start_drag_internal);
2753 console_type_create_frame_x (void)
2756 CONSOLE_HAS_METHOD (x, init_frame_1);
2757 CONSOLE_HAS_METHOD (x, init_frame_2);
2758 CONSOLE_HAS_METHOD (x, init_frame_3);
2759 CONSOLE_HAS_METHOD (x, mark_frame);
2760 CONSOLE_HAS_METHOD (x, focus_on_frame);
2761 CONSOLE_HAS_METHOD (x, delete_frame);
2762 CONSOLE_HAS_METHOD (x, get_mouse_position);
2763 CONSOLE_HAS_METHOD (x, set_mouse_position);
2764 CONSOLE_HAS_METHOD (x, raise_frame);
2765 CONSOLE_HAS_METHOD (x, lower_frame);
2766 CONSOLE_HAS_METHOD (x, make_frame_visible);
2767 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2768 CONSOLE_HAS_METHOD (x, iconify_frame);
2769 CONSOLE_HAS_METHOD (x, set_frame_size);
2770 CONSOLE_HAS_METHOD (x, set_frame_position);
2771 CONSOLE_HAS_METHOD (x, frame_property);
2772 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2773 CONSOLE_HAS_METHOD (x, frame_properties);
2774 CONSOLE_HAS_METHOD (x, set_frame_properties);
2775 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2776 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2777 CONSOLE_HAS_METHOD (x, frame_visible_p);
2778 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2779 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2780 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2781 CONSOLE_HAS_METHOD (x, set_frame_icon);
2782 CONSOLE_HAS_METHOD (x, get_frame_parent);
2783 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2787 vars_of_frame_x (void)
2789 #ifdef EXTERNAL_WIDGET
2790 Fprovide (intern ("external-widget"));
2793 /* this call uses only safe functions from emacs.c */
2794 init_x_prop_symbols ();
2796 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2797 Plist of default frame-creation properties for X frames.
2798 These override what is specified in the resource database and in
2799 `default-frame-plist', but are overridden by the arguments to the
2800 particular call to `make-frame'.
2802 Note: In many cases, properties of a frame are available as specifiers
2803 instead of through the frame-properties mechanism.
2805 Here is a list of recognized frame properties, other than those
2806 documented in `set-frame-properties' (they can be queried and
2807 set at any time, except as otherwise noted):
2809 window-id The X window ID corresponding to the
2810 frame. May be set only at startup, and
2811 only if external widget support was
2812 compiled in; doing so causes the frame
2813 to be created as an "external widget"
2814 in another program that uses an existing
2815 window in the program rather than creating
2817 initially-unmapped If non-nil, the frame will not be visible
2818 when it is created. In this case, you
2819 need to call `make-frame-visible' to make
2821 popup If non-nil, it should be a frame, and this
2822 frame will be created as a "popup" frame
2823 whose parent is the given frame. This
2824 will make the window manager treat the
2825 frame as a dialog box, which may entail
2826 doing different things (e.g. not asking
2827 for positioning, and not iconifying
2828 separate from its parent).
2829 inter-line-space Not currently implemented.
2830 toolbar-shadow-thickness Thickness of toolbar shadows.
2831 background-toolbar-color Color of toolbar background.
2832 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2833 (*Not* specific to the bottom-toolbar.)
2834 top-toolbar-shadow-color Color of top shadows on toolbars.
2835 (*Not* specific to the top-toolbar.)
2836 internal-border-width Width of internal border around text area.
2837 border-width Width of external border around text area.
2838 top Y position (in pixels) of the upper-left
2839 outermost corner of the frame (i.e. the
2840 upper-left of the window-manager
2842 left X position (in pixels) of the upper-left
2843 outermost corner of the frame (i.e. the
2844 upper-left of the window-manager
2846 border-color Color of external border around text area.
2847 cursor-color Color of text cursor.
2849 See also `default-frame-plist', which specifies properties which apply
2850 to all frames, not just X frames.
2852 Vdefault_x_frame_plist = Qnil;
2854 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;