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. */
26 /* 7-8-00 !!#### This file needs definite Mule review. */
31 #include "console-x.h"
32 #include "xintrinsicp.h" /* CoreP.h needs this */
33 #include <X11/CoreP.h> /* Numerous places access the fields of
34 a core widget directly. We could
35 use XtGetValues(), but ... */
36 #include <X11/Shell.h>
37 #include <X11/ShellP.h>
39 #include "EmacsManager.h"
40 #include "EmacsFrameP.h"
41 #include "EmacsShell.h"
42 #ifdef EXTERNAL_WIDGET
43 #include "ExternalShell.h"
46 #include "objects-x.h"
47 #include "scrollbar-x.h"
64 #if defined (HAVE_OFFIX_DND) || defined (HAVE_CDE)
65 #include "events-mod.h"
68 /* Default properties to use when creating frames. */
69 Lisp_Object Vdefault_x_frame_plist;
71 Lisp_Object Qwindow_id;
72 Lisp_Object Qx_resource_name;
74 EXFUN (Fx_window_id, 1);
77 /************************************************************************/
78 /* helper functions */
79 /************************************************************************/
81 /* Return the Emacs frame-object corresponding to an X window */
83 x_window_to_frame (struct device *d, Window wdesc)
85 Lisp_Object tail, frame;
88 /* This function was previously written to accept only a window argument
89 (and to loop over all devices looking for a matching window), but
90 that is incorrect because window ID's are not unique across displays. */
92 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
98 if (FRAME_X_P (f) && XtWindow (FRAME_X_TEXT_WIDGET (f)) == wdesc)
104 /* Like x_window_to_frame but also compares the window with the widget's
107 x_any_window_to_frame (struct device *d, Window wdesc)
110 assert (DEVICE_X_P (d));
112 w = XtWindowToWidget (DEVICE_X_DISPLAY (d), wdesc);
117 /* We used to map over all frames here and then map over all widgets
118 belonging to that frame. However it turns out that this was very fragile
119 as it requires our display structures to be in sync _and_ that the
120 loop is told about every new widget somebody adds. Therefore we
121 now let Xt find it for us (which does a bottom-up search which
122 could even be faster) */
123 return x_any_widget_or_parent_to_frame (d, w);
126 static struct frame *
127 x_find_frame_for_window (struct device *d, Window wdesc)
129 Lisp_Object tail, frame;
131 /* This function was previously written to accept only a window argument
132 (and to loop over all devices looking for a matching window), but
133 that is incorrect because window ID's are not unique across displays. */
135 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
139 /* This frame matches if the window is any of its widgets. */
140 if (wdesc == XtWindow (FRAME_X_SHELL_WIDGET (f)) ||
141 wdesc == XtWindow (FRAME_X_CONTAINER_WIDGET (f)) ||
142 wdesc == XtWindow (FRAME_X_TEXT_WIDGET (f)))
145 /* Match if the window is one of the widgets at the top of the frame
146 (menubar, Energize psheets). */
148 /* Note: Jamie once said
150 "Do *not* match if the window is this frame's psheet."
152 But this is wrong and will screw up some functions that expect
153 x_any_window_to_frame() to work as advertised. I think the reason
154 for this statement is that, in the old (broken) event loop, where
155 not all events went through XtDispatchEvent(), psheet events
156 would incorrectly get sucked away by Emacs if this function matched
157 on psheet widgets. */
159 /* Note: that this called only from
160 x_any_widget_or_parent_to_frame it is unnecessary to iterate
161 over the top level widgets. */
163 /* Note: we use to special case scrollbars but this turns out to be a bad idea
165 1. We sometimes get events for _unmapped_ scrollbars and our
166 callers don't want us to fail.
167 2. Starting with the 21.2 widget stuff there are now loads of
168 widgets to check and it is easy to forget adding them in a loop here.
169 See x_any_window_to_frame
170 3. We pick up all widgets now anyway. */
177 x_any_widget_or_parent_to_frame (struct device *d, Widget widget)
181 struct frame *f = x_find_frame_for_window (d, XtWindow (widget));
184 widget = XtParent (widget);
191 decode_x_frame (Lisp_Object frame)
194 XSETFRAME (frame, selected_frame ());
195 CHECK_LIVE_FRAME (frame);
196 /* this will also catch dead frames, but putting in the above check
197 results in a more useful error */
198 CHECK_X_FRAME (frame);
199 return XFRAME (frame);
203 /************************************************************************/
204 /* window-manager interactions */
205 /************************************************************************/
208 /* Not currently used. */
211 x_wm_mark_shell_size_user_specified (Widget wmshell)
213 if (! XtIsWMShell (wmshell)) abort ();
214 EmacsShellSetSizeUserSpecified (wmshell);
218 x_wm_mark_shell_position_user_specified (Widget wmshell)
220 if (! XtIsWMShell (wmshell)) abort ();
221 EmacsShellSetPositionUserSpecified (wmshell);
227 x_wm_set_shell_iconic_p (Widget shell, int iconic_p)
229 if (! XtIsWMShell (shell)) abort ();
231 /* Because of questionable logic in Shell.c, this sequence can't work:
233 w = XtCreatePopupShell (...);
234 Xt_SET_VALUE (w, XtNiconic, True);
237 The iconic resource is only consulted at initialization time (when
238 XtCreatePopupShell is called) instead of at realization time (just
239 before the window gets created, which would be more sensible) or
240 at management-time (just before the window gets mapped, which would
241 be most sensible of all).
243 The bug is that Shell's SetValues method doesn't do anything to
244 w->wm.wm_hints.initial_state until after the widget has been realized.
245 Calls to XtSetValues are ignored in the window between creation and
246 realization. This is true of MIT X11R5 patch level 25, at least.
247 (Apparently some other versions of Xt don't have this bug?)
249 Xt_SET_VALUE (shell, XtNiconic, iconic_p);
250 EmacsShellSmashIconicHint (shell, iconic_p);
254 x_wm_set_cell_size (Widget wmshell, int cw, int ch)
258 if (!XtIsWMShell (wmshell))
260 if (cw <= 0 || ch <= 0)
263 XtSetArg (al [0], XtNwidthInc, cw);
264 XtSetArg (al [1], XtNheightInc, ch);
265 XtSetValues (wmshell, al, 2);
269 x_wm_set_variable_size (Widget wmshell, int width, int height)
273 if (!XtIsWMShell (wmshell))
275 #ifdef DEBUG_GEOMETRY_MANAGEMENT
276 /* See comment in EmacsShell.c */
277 printf ("x_wm_set_variable_size: %d %d\n", width, height);
281 XtSetArg (al [0], XtNwidthCells, width);
282 XtSetArg (al [1], XtNheightCells, height);
283 XtSetValues (wmshell, al, 2);
286 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS
287 and WM_DELETE_WINDOW, then add them. (They may already be present
288 because of the toolkit (Motif adds them, for example, but Xt doesn't).
291 x_wm_hack_wm_protocols (Widget widget)
293 Display *dpy = XtDisplay (widget);
294 struct device *d = get_device_from_display (dpy);
295 Window w = XtWindow (widget);
299 assert (XtIsWMShell (widget));
302 Atom type, *atoms = 0;
304 unsigned long nitems = 0;
305 unsigned long bytes_after;
307 if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d),
308 0, 100, False, XA_ATOM,
309 &type, &format, &nitems, &bytes_after,
310 (unsigned char **) &atoms)
311 && format == 32 && type == XA_ATOM)
315 if (atoms [nitems] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
317 else if (atoms [nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
320 if (atoms) XFree ((char *) atoms);
325 if (need_delete) props[count++] = DEVICE_XATOM_WM_DELETE_WINDOW (d);
326 if (need_focus) props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d);
328 XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32,
329 PropModeAppend, (unsigned char *) props, count);
334 x_wm_store_class_hints (Widget shell, char *frame_name)
336 Display *dpy = XtDisplay (shell);
337 char *app_name, *app_class;
338 XClassHint classhint;
340 if (!XtIsWMShell (shell))
343 XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
344 classhint.res_name = frame_name;
345 classhint.res_class = app_class;
346 XSetClassHint (dpy, XtWindow (shell), &classhint);
349 #ifndef HAVE_WMCOMMAND
351 x_wm_maybe_store_wm_command (struct frame *f)
353 Widget w = FRAME_X_SHELL_WIDGET (f);
354 struct device *d = XDEVICE (FRAME_DEVICE (f));
356 if (!XtIsWMShell (w))
359 if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
363 make_argc_argv (Vcommand_line_args, &argc, &argv);
364 XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
365 free_argc_argv (argv);
366 XSETFRAME (DEVICE_X_WM_COMMAND_FRAME (d), f);
370 /* If we're deleting the frame on which the WM_COMMAND property has been
371 set, then move that property to another frame so that there is exactly
372 one frame that has that property set.
375 x_wm_maybe_move_wm_command (struct frame *f)
377 struct device *d = XDEVICE (FRAME_DEVICE (f));
379 /* There may not be a frame in DEVICE_X_WM_COMMAND_FRAME()
380 if we C-c'ed at startup at the right time. */
381 if (FRAMEP (DEVICE_X_WM_COMMAND_FRAME (d))
382 && f == XFRAME (DEVICE_X_WM_COMMAND_FRAME (d)))
384 Lisp_Object rest = DEVICE_FRAME_LIST (d);
385 DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
386 /* find some random other X frame that is not this one, or give up */
387 /* skip non-top-level (ExternalClient) frames */
388 while (!NILP (rest) &&
389 (f == XFRAME (XCAR (rest)) ||
390 !FRAME_X_TOP_LEVEL_FRAME_P (XFRAME (XCAR (rest)))))
394 f = XFRAME (XCAR (rest));
396 x_wm_maybe_store_wm_command (f);
400 #endif /* !HAVE_WMCOMMAND */
403 x_frame_iconified_p (struct frame *f)
407 unsigned long nitems, bytesafter;
408 unsigned long *datap = 0;
411 struct device *d = XDEVICE (FRAME_DEVICE (f));
413 widget = FRAME_X_SHELL_WIDGET (f);
414 if (Success == XGetWindowProperty (XtDisplay (widget), XtWindow (widget),
415 DEVICE_XATOM_WM_STATE (d), 0, 2, False,
416 DEVICE_XATOM_WM_STATE (d), &actual_type,
417 &actual_format, &nitems, &bytesafter,
418 (unsigned char **) &datap)
421 if (nitems <= 2 /* "suggested" by ICCCM version 1 */
422 && datap[0] == IconicState)
424 XFree ((char *) datap);
430 /************************************************************************/
431 /* frame properties */
432 /************************************************************************/
434 /* Connect the frame-property names (symbols) to the corresponding
435 X Resource Manager names. The name of a property, as a Lisp symbol,
436 has an `x-resource-name' property which is a Lisp_String. */
439 init_x_prop_symbols (void)
441 #define def(sym, rsrc) \
442 Fput (sym, Qx_resource_name, build_string (rsrc))
443 #define defi(sym,rsrc) \
444 def (sym, rsrc); Fput (sym, Qintegerp, Qt)
446 #if 0 /* this interferes with things. #### fix this right */
447 def (Qminibuffer, XtNminibuffer);
448 def (Qunsplittable, XtNunsplittable);
450 defi(Qinternal_border_width, XtNinternalBorderWidth);
452 def (Qtop_toolbar_shadow_color, XtNtopToolBarShadowColor);
453 def (Qbottom_toolbar_shadow_color, XtNbottomToolBarShadowColor);
454 def (Qbackground_toolbar_color, XtNbackgroundToolBarColor);
455 def (Qtop_toolbar_shadow_pixmap, XtNtopToolBarShadowPixmap);
456 def (Qbottom_toolbar_shadow_pixmap, XtNbottomToolBarShadowPixmap);
457 defi(Qtoolbar_shadow_thickness, XtNtoolBarShadowThickness);
459 def (Qscrollbar_placement, XtNscrollBarPlacement);
460 defi(Qinter_line_space, XtNinterline);
461 /* font, foreground */
462 def (Qiconic, XtNiconic);
463 def (Qbar_cursor, XtNbarCursor);
464 def (Qvisual_bell, XtNvisualBell);
465 defi(Qbell_volume, XtNbellVolume);
466 def (Qpointer_background, XtNpointerBackground);
467 def (Qpointer_color, XtNpointerColor);
468 def (Qtext_pointer, XtNtextPointer);
469 def (Qspace_pointer, XtNspacePointer);
470 def (Qmodeline_pointer, XtNmodeLinePointer);
471 def (Qgc_pointer, XtNgcPointer);
472 /* geometry, initial_geometry */
473 def (Qinitially_unmapped, XtNinitiallyUnmapped);
474 /* preferred_width, preferred_height */
475 def (Quse_backing_store, XtNuseBackingStore);
479 def (Qborder_color, XtNborderColor);
480 defi(Qborder_width, XtNborderWidth);
481 defi(Qwidth, XtNwidth);
482 defi(Qheight, XtNheight);
490 color_to_string (Widget w, unsigned long pixel)
496 XQueryColor (XtDisplay (w), w->core.colormap, &color);
497 sprintf (buf, "#%04x%04x%04x", color.red, color.green, color.blue);
498 return build_string (buf);
502 x_get_top_level_position (Display *d, Window w, Position *x, Position *y)
504 Window root, parent = w, *children;
505 unsigned int nchildren;
506 XWindowAttributes xwa;
511 if (!XQueryTree (d, w, &root, &parent, &children, &nchildren))
519 while (root != parent);
520 XGetWindowAttributes (d, w, &xwa);
527 x_smash_bastardly_shell_position (Widget shell)
529 /* Naturally those bastards who wrote Xt couldn't be bothered
530 to learn about race conditions and such. We can't trust
531 the X and Y values to have any semblance of correctness,
532 so we smash the right values in place. */
534 /* We might be called before we've actually realized the window (if
535 we're checking for the minibuffer resource). This will bomb in
536 that case so we don't bother calling it. */
537 if (XtWindow (shell))
538 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
539 &shell->core.x, &shell->core.y);
544 x_frame_property (struct frame *f, Lisp_Object property)
546 Widget shell = FRAME_X_SHELL_WIDGET (f);
547 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
548 Widget gw = (Widget) w;
550 if (EQ (Qleft, property) || EQ (Qtop, property))
553 if (!XtWindow(shell))
555 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
556 if (EQ (Qleft, property)) return make_int (x);
557 if (EQ (Qtop, property)) return make_int (y);
559 if (EQ (Qborder_width, property))
560 return make_int (w->core.border_width);
561 if (EQ (Qinternal_border_width, property))
562 return make_int (w->emacs_frame.internal_border_width);
563 if (EQ (Qborder_color, property))
564 return color_to_string (gw, w->core.border_pixel);
566 if (EQ (Qtop_toolbar_shadow_color, property))
567 return color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel);
568 if (EQ (Qbottom_toolbar_shadow_color, property))
569 return color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel);
570 if (EQ (Qbackground_toolbar_color, property))
571 return color_to_string (gw, w->emacs_frame.background_toolbar_pixel);
572 if (EQ (Qtoolbar_shadow_thickness, property))
573 return make_int (w->emacs_frame.toolbar_shadow_thickness);
574 #endif /* HAVE_TOOLBARS */
575 if (EQ (Qinter_line_space, property))
576 return make_int (w->emacs_frame.interline);
577 if (EQ (Qwindow_id, property))
578 return Fx_window_id (make_frame (f));
584 x_internal_frame_property_p (struct frame *f, Lisp_Object property)
586 return EQ (property, Qleft)
587 || EQ (property, Qtop)
588 || EQ (property, Qborder_width)
589 || EQ (property, Qinternal_border_width)
590 || EQ (property, Qborder_color)
592 || EQ (property, Qtop_toolbar_shadow_color)
593 || EQ (property, Qbottom_toolbar_shadow_color)
594 || EQ (property, Qbackground_toolbar_color)
595 || EQ (property, Qtoolbar_shadow_thickness)
596 #endif /* HAVE_TOOLBARS */
597 || EQ (property, Qinter_line_space)
598 || EQ (property, Qwindow_id)
599 || STRINGP (property);
603 x_frame_properties (struct frame *f)
605 Lisp_Object props = Qnil;
606 Widget shell = FRAME_X_SHELL_WIDGET (f);
607 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
608 Widget gw = (Widget) w;
611 props = cons3 (Qwindow_id, Fx_window_id (make_frame (f)), props);
612 props = cons3 (Qinter_line_space, make_int (w->emacs_frame.interline), props);
615 props = cons3 (Qtoolbar_shadow_thickness,
616 make_int (w->emacs_frame.toolbar_shadow_thickness),
618 props = cons3 (Qbackground_toolbar_color,
619 color_to_string (gw, w->emacs_frame.background_toolbar_pixel),
621 props = cons3 (Qbottom_toolbar_shadow_color,
622 color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel),
624 props = cons3 (Qtop_toolbar_shadow_color,
625 color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel),
627 #endif /* HAVE_TOOLBARS */
629 props = cons3 (Qborder_color,
630 color_to_string (gw, w->core.border_pixel), props);
631 props = cons3 (Qinternal_border_width,
632 make_int (w->emacs_frame.internal_border_width), props);
633 props = cons3 (Qborder_width, make_int (w->core.border_width), props);
635 if (!XtWindow(shell))
638 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
640 props = cons3 (Qtop, make_int (y), props);
641 props = cons3 (Qleft, make_int (x), props);
647 /* Functions called only from `x_set_frame_properties' to set
648 individual properties. */
651 x_set_frame_text_value (struct frame *f, Bufbyte *value,
652 String Xt_resource_name,
653 String Xt_resource_encoding_name)
655 Atom encoding = XA_STRING;
656 String new_XtValue = (String) value;
657 String old_XtValue = NULL;
661 /* Optimize for common ASCII case */
662 for (ptr = value; *ptr; ptr++)
663 if (!BYTE_ASCII_P (*ptr))
666 encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f)));
667 C_STRING_TO_EXTERNAL (value, tmp, Qctext);
668 new_XtValue = (String) tmp;
673 /* #### Caching is device-independent - belongs in update_frame_title. */
674 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
675 if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
678 XtSetArg (al[0], Xt_resource_name, new_XtValue);
679 XtSetArg (al[1], Xt_resource_encoding_name, encoding);
680 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
685 x_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
687 x_set_frame_text_value (f, name, XtNtitle, XtNtitleEncoding);
691 x_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
693 x_set_frame_text_value (f, name, XtNiconName, XtNiconNameEncoding);
696 /* Set the initial frame size as specified. This function is used
697 when the frame's widgets have not yet been realized. In this
698 case, it is not sufficient just to set the width and height of
699 the EmacsFrame widget, because they will be ignored when the
700 widget is realized (instead, the shell's geometry resource is
704 x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
705 unsigned int w, unsigned int h)
707 char shell_geom [255];
710 char uspos = !!(flags & (XValue | YValue));
711 char ussize = !!(flags & (WidthValue | HeightValue));
714 /* assign the correct size to the EmacsFrame widget ... */
715 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
717 /* and also set the WMShell's geometry */
718 (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
719 (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
722 sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
724 sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
726 sprintf (shell_geom, "=%dx%d", w, h);
730 temp = (char *) xmalloc (1 + strlen (shell_geom));
731 strcpy (temp, shell_geom);
732 FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
737 Xt_SET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp);
740 /* Report to X that a frame property of frame S is being set or changed.
741 If the property is not specially recognized, do nothing.
745 x_set_frame_properties (struct frame *f, Lisp_Object plist)
748 Dimension width = 0, height = 0;
749 Bool width_specified_p = False;
750 Bool height_specified_p = False;
751 Bool x_position_specified_p = False;
752 Bool y_position_specified_p = False;
753 Bool internal_border_width_specified = False;
755 Widget w = FRAME_X_TEXT_WIDGET (f);
757 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
759 Lisp_Object prop = Fcar (tail);
760 Lisp_Object val = Fcar (Fcdr (tail));
766 if (XSTRING_LENGTH (prop) == 0)
769 LISP_STRING_TO_EXTERNAL (prop, extprop, Qctext);
772 const Extbyte *extval;
775 TO_EXTERNAL_FORMAT (LISP_STRING, val,
776 ALLOCA, (extval, extvallen),
778 XtVaSetValues (w, XtVaTypedArg, extprop,
779 XtRString, extval, extvallen + 1,
783 XtVaSetValues (w, XtVaTypedArg, extprop, XtRInt,
784 XINT (val), sizeof (int),
787 else if (SYMBOLP (prop))
789 Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
790 int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
792 if (NILP (prop) || NILP (str))
794 /* Kludge to handle the font property. */
795 if (EQ (prop, Qfont))
797 /* If the value is not a string we silently ignore it. */
800 Lisp_Object frm, font_spec;
803 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
805 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
806 update_frame_face_values (f);
816 /* Kludge the width/height so that we interpret them in characters
817 instead of pixels. Yuck yuck yuck. */
818 if (!strcmp ((char *) XSTRING_DATA (str), "width"))
822 width_specified_p = True;
825 if (!strcmp ((char *) XSTRING_DATA (str), "height"))
829 height_specified_p = True;
832 /* Further kludge the x/y. */
833 if (!strcmp ((char *) XSTRING_DATA (str), "x"))
836 x = (Position) XINT (val);
837 x_position_specified_p = True;
840 if (!strcmp ((char *) XSTRING_DATA (str), "y"))
843 y = (Position) XINT (val);
844 y_position_specified_p = True;
847 /* Have you figured out by now that this entire function is
848 one gigantic kludge? */
849 if (!strcmp ((char *) XSTRING_DATA (str),
850 "internalBorderWidth"))
852 internal_border_width_specified = True;
858 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val));
860 else if (EQ (val, Qt))
862 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/
864 else if (EQ (val, Qnil))
866 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/
871 XtVaSetValues (w, XtVaTypedArg,
873 (char *) XSTRING_DATA (str),
876 XSTRING_LENGTH (val) + 1,
880 #ifdef HAVE_SCROLLBARS
881 if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth")
882 || !strcmp ((char *) XSTRING_DATA (str),
885 x_update_frame_scrollbars (f);
887 #endif /* HAVE_SCROLLBARS */
891 /* Kludge kludge kludge. We need to deal with the size and position
894 int size_specified_p = width_specified_p || height_specified_p;
895 int position_specified_p = x_position_specified_p ||
896 y_position_specified_p;
898 if (!width_specified_p)
899 width = FRAME_WIDTH (f);
900 if (!height_specified_p)
901 height = FRAME_HEIGHT (f);
903 /* Kludge kludge kludge kludge. */
904 if (position_specified_p &&
905 (!x_position_specified_p || !y_position_specified_p))
908 Widget shell = FRAME_X_SHELL_WIDGET (f);
909 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
910 (x_position_specified_p ? &dummy : &x),
911 (y_position_specified_p ? &dummy : &y));
913 x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
914 y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
918 if (!f->init_finished)
920 int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
921 (position_specified_p ?
922 XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
925 || position_specified_p
926 || internal_border_width_specified)
927 x_set_initial_frame_size (f, flags, x, y, width, height);
931 if (size_specified_p || internal_border_width_specified)
934 XSETFRAME (frame, f);
935 Fset_frame_size (frame, make_int (width),
936 make_int (height), Qnil);
938 if (position_specified_p)
941 XSETFRAME (frame, f);
942 Fset_frame_position (frame, make_int (x), make_int (y));
948 static int frame_title_format_already_set;
951 maybe_set_frame_title_format (Widget shell)
954 /* Only do this if this is the first X frame we're creating.
956 If the *title resource (or -title option) was specified, then
957 set frame-title-format to its value.
960 if (!frame_title_format_already_set)
962 /* No doubt there's a less stupid way to do this. */
964 XtResource resources [2];
965 results [0] = results [1] = 0;
966 resources [0].resource_name = XtNtitle;
967 resources [0].resource_class = XtCTitle;
968 resources [0].resource_type = XtRString;
969 resources [0].resource_size = sizeof (String);
970 resources [0].resource_offset = 0;
971 resources [0].default_type = XtRString;
972 resources [0].default_addr = 0;
973 resources [1].resource_name = XtNiconName;
974 resources [1].resource_class = XtCIconName;
975 resources [1].resource_type = XtRString;
976 resources [1].resource_size = sizeof (String);
977 resources [1].resource_offset = sizeof (char *);
978 resources [1].default_type = XtRString;
979 resources [1].default_addr = 0;
980 XtGetSubresources (XtParent (shell), (XtPointer) results,
982 shell->core.widget_class->core_class.class_name,
983 resources, XtNumber (resources), 0, 0);
985 Vframe_title_format = build_string (results[0]);
987 Vframe_icon_title_format = build_string (results[1]);
990 frame_title_format_already_set = 1;
997 static Widget CurrentDragWidget = NULL;
998 static XtCallbackRec dnd_convert_cb_rec[2];
999 static XtCallbackRec dnd_destroy_cb_rec[2];
1000 static int drag_not_done = 0;
1003 x_cde_destroy_callback (Widget widget, XtPointer clientData,
1006 DtDndDragFinishCallbackStruct *dragFinishInfo =
1007 (DtDndDragFinishCallbackStruct *)callData;
1008 DtDndContext *dragData = dragFinishInfo->dragData;
1011 /* free the items */
1012 if (callData != NULL && dragData != NULL)
1014 if (dragData->protocol == DtDND_BUFFER_TRANSFER)
1016 for (i = 0; i < dragData->numItems; i++)
1018 XtFree((char *) dragData->data.buffers[i].bp);
1019 if (dragData->data.buffers[i].name)
1020 XtFree(dragData->data.buffers[i].name);
1025 for (i = 0; i < dragData->numItems; i++)
1026 XtFree(dragData->data.files[i]);
1030 /* free the data string */
1033 CurrentDragWidget = NULL;
1037 x_cde_convert_callback (Widget widget, XtPointer clientData,
1040 DtDndConvertCallbackStruct *convertInfo =
1041 (DtDndConvertCallbackStruct *) callData;
1042 char *textdata = (char *) clientData;
1043 char *textptr = NULL;
1046 if (convertInfo == NULL)
1051 if ((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER
1052 && convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER) ||
1053 (convertInfo->reason != DtCR_DND_CONVERT_DATA))
1058 for (textptr=textdata, i=0;
1059 i<convertInfo->dragData->numItems;
1060 textptr+=strlen(textptr)+1, i++)
1062 if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER)
1064 convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr);
1065 convertInfo->dragData->data.buffers[i].size = strlen(textptr);
1066 convertInfo->dragData->data.buffers[i].name = NULL;
1070 convertInfo->dragData->data.files[i] = XtNewString(textptr);
1074 convertInfo->status = DtDND_SUCCESS;
1078 abort_current_drag(Lisp_Object arg)
1080 if (CurrentDragWidget && drag_not_done)
1082 XmDragCancel(CurrentDragWidget);
1083 CurrentDragWidget = NULL;
1088 DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 3, 3, 0, /*
1089 Start a CDE drag from a buffer.
1090 First argument is the event that started the drag (must be a
1091 button-press-event),
1092 second arg defines if the data should be treated as a buffer or
1093 a filename transfer (set to nil for buffer transfer),
1094 and the third argument is a list of data strings.
1095 WARNING: can only handle plain/text and file: transfers!
1097 (event, dragtype, dragdata))
1101 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1103 Widget wid = FRAME_X_TEXT_WIDGET (f);
1104 Display *display = XtDisplayOfObject (wid);
1105 struct device *d = get_device_from_display (display);
1106 struct x_device *xd = DEVICE_X_DATA (d);
1107 XWindowAttributes win_attrib;
1108 unsigned int modifier = 0, state = 0;
1110 int numItems = 0, textlen = 0, pos = 0;
1111 Lisp_Event *lisp_event = XEVENT (event);
1112 Lisp_Object item = Qnil;
1113 struct gcpro gcpro1;
1115 /* only drag if this is really a press */
1116 if (EVENT_TYPE(lisp_event) != button_press_event
1117 || !LISTP(dragdata))
1123 * not so cross hack that converts a emacs event back to a XEvent
1126 x_event.xbutton.type = ButtonPress;
1127 x_event.xbutton.send_event = False;
1128 x_event.xbutton.display = XtDisplayOfObject(wid);
1129 x_event.xbutton.window = XtWindowOfObject(wid);
1130 x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0);
1131 x_event.xbutton.subwindow = 0;
1132 x_event.xbutton.time = lisp_event->timestamp;
1133 x_event.xbutton.x = lisp_event->event.button.x;
1134 x_event.xbutton.y = lisp_event->event.button.y;
1135 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1136 x_event.xbutton.window,
1139 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1140 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1144 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1145 x_event.xbutton.y_root = lisp_event->event.button.y;
1147 modifier = lisp_event->event.button.modifiers;
1148 if (modifier & XEMACS_MOD_SHIFT) state |= ShiftMask;
1149 if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask;
1150 if (modifier & XEMACS_MOD_META) state |= xd->MetaMask;
1151 if (modifier & XEMACS_MOD_SUPER) state |= xd->SuperMask;
1152 if (modifier & XEMACS_MOD_HYPER) state |= xd->HyperMask;
1153 if (modifier & XEMACS_MOD_ALT) state |= xd->AltMask;
1154 state |= Button1Mask << (lisp_event->event.button.button-1);
1156 x_event.xbutton.state = state;
1157 x_event.xbutton.button = lisp_event->event.button.button;
1158 x_event.xkey.same_screen = True;
1160 /* convert data strings into a big string */
1162 while (!NILP (item))
1164 if (!STRINGP (XCAR (item)))
1169 textlen += XSTRING_LENGTH (XCAR (item)) + 1;
1177 * concatenate all strings given to one large string, with
1178 * \0 as separator. List is ended by \0.
1180 Ctext = (char *)xmalloc (textlen+1);
1184 while (!NILP (item))
1186 if (!STRINGP (XCAR (item)))
1193 strcpy (Ctext+pos, (const char *)XSTRING_DATA (XCAR (item)));
1194 pos += XSTRING_LENGTH (XCAR (item)) + 1;
1199 dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
1200 dnd_convert_cb_rec[0].closure = (XtPointer) Ctext;
1201 dnd_convert_cb_rec[1].callback = NULL;
1202 dnd_convert_cb_rec[1].closure = NULL;
1204 dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
1205 dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext;
1206 dnd_destroy_cb_rec[1].callback = NULL;
1207 dnd_destroy_cb_rec[1].closure = NULL;
1210 DtDndDragStart (wid, &x_event,
1211 (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER),
1221 return numItems?Qt:Qnil;
1228 x_cde_transfer_callback (Widget widget, XtPointer clientData,
1231 char *filePath, *hurl;
1233 Lisp_Object frame = Qnil;
1234 Lisp_Object l_type = Qnil;
1235 Lisp_Object l_data = Qnil;
1236 DtDndTransferCallbackStruct *transferInfo = NULL;
1237 struct gcpro gcpro1, gcpro2, gcpro3;
1240 this needs to be changed to the new protocol:
1241 - we need the button, modifier and pointer states to create a
1242 correct misc_user_event
1243 - the data must be converted to the new format (URL/MIME)
1247 transferInfo = (DtDndTransferCallbackStruct *) callData;
1248 if (transferInfo == NULL)
1251 GCPRO3 (frame, l_type, l_data);
1253 frame = make_frame ((struct frame *) clientData);
1255 if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
1257 l_type = Qdragdrop_URL;
1259 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1261 filePath = transferInfo->dropData->data.files[ii];
1262 hurl = dnd_url_hexify_string ((char *)filePath, "file:");
1263 /* #### Mule-izing required */
1264 l_data = Fcons (make_string ((Bufbyte* )hurl,
1270 else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
1272 int speccount = specpdl_depth();
1274 /* Problem: all buffers a treated as text/plain!!!
1275 Solution: Also support DtDND_TEXT_TRANSFER
1276 perhaps implementation of the Motif protocol
1277 (which is the base of CDE) will clear this */
1278 l_type = Qdragdrop_MIME;
1279 record_unwind_protect(abort_current_drag, Qnil);
1281 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1283 /* let us forget this name thing for now... */
1284 /* filePath = transferInfo->dropData->data.buffers[ii].name;
1285 path = (filePath == NULL) ? Qnil
1286 : make_string ((Bufbyte *)filePath, strlen (filePath)); */
1287 /* what, if the data is no text, and how can I tell it? */
1288 l_data = Fcons ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1289 make_string ((Bufbyte *)"8bit", 4),
1290 make_string ((Bufbyte *)transferInfo->dropData->data.buffers[ii].bp,
1291 transferInfo->dropData->data.buffers[ii].size) ),
1295 unbind_to(speccount, Qnil);
1297 else /* the other cases: NOOP_TRANSFER */
1300 /* The Problem: no button and mods from CDE... */
1302 enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch,
1303 Fcons (l_type, l_data),
1304 0 /* this is the button */,
1305 0 /* these are the mods */,
1312 #endif /* HAVE_CDE */
1314 #ifdef HAVE_OFFIX_DND
1316 DEFUN ("offix-start-drag-internal", Foffix_start_drag_internal, 2, 3, 0, /*
1317 Start a OffiX drag from a buffer.
1318 First arg is the event that started the drag,
1319 second arg should be some string, and the third
1320 is the type of the data (this should be an int).
1321 The type defaults to DndText (4).
1323 (event, data, dtyp))
1327 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1329 Widget wid = FRAME_X_TEXT_WIDGET (f);
1330 Display *display = XtDisplayOfObject (wid);
1331 struct device *d = get_device_from_display (display);
1332 struct x_device *xd = DEVICE_X_DATA (d);
1333 XWindowAttributes win_attrib;
1334 unsigned int modifier = 0, state = 0;
1335 char *dnd_data = NULL;
1336 unsigned long dnd_len = 0;
1337 int dnd_typ = DndText, dnd_dealloc = 0;
1338 Lisp_Event *lisp_event = XEVENT (event);
1340 /* only drag if this is really a press */
1341 if (EVENT_TYPE(lisp_event) != button_press_event)
1344 /* get the desired type */
1345 if (!NILP (dtyp) && INTP (dtyp))
1346 dnd_typ = XINT (dtyp);
1348 if (dnd_typ == DndFiles)
1350 Lisp_Object run = data;
1353 if (NILP ( Flistp (data)))
1356 /* construct the data from a list of files */
1358 dnd_data = (char *) xmalloc (1);
1362 if (!STRINGP (XCAR (run)))
1367 len = XSTRING_LENGTH (XCAR (run)) + 1;
1368 dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
1369 strcpy (dnd_data + dnd_len - 1, (const char *)XSTRING_DATA (XCAR (run)));
1374 dnd_data[dnd_len - 1] = 0; /* the list-ending zero */
1380 if (!STRINGP (data))
1383 /* and what's with MULE data ??? */
1384 dnd_data = (char *)XSTRING_DATA (data);
1385 dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */
1389 /* not so gross hack that converts an emacs event back to a XEvent */
1391 x_event.xbutton.type = ButtonPress;
1392 x_event.xbutton.send_event = False;
1393 x_event.xbutton.display = XtDisplayOfObject(wid);
1394 x_event.xbutton.window = XtWindowOfObject(wid);
1395 x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0);
1396 x_event.xbutton.subwindow = 0;
1397 x_event.xbutton.time = lisp_event->timestamp;
1398 x_event.xbutton.x = lisp_event->event.button.x;
1399 x_event.xbutton.y = lisp_event->event.button.y;
1400 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1401 x_event.xbutton.window,
1404 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1405 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1409 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1410 x_event.xbutton.y_root = lisp_event->event.button.y;
1413 modifier = lisp_event->event.button.modifiers;
1414 if (modifier & XEMACS_MOD_SHIFT) state |= ShiftMask;
1415 if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask;
1416 if (modifier & XEMACS_MOD_META) state |= xd->MetaMask;
1417 if (modifier & XEMACS_MOD_SUPER) state |= xd->SuperMask;
1418 if (modifier & XEMACS_MOD_HYPER) state |= xd->HyperMask;
1419 if (modifier & XEMACS_MOD_ALT) state |= xd->AltMask;
1420 state |= Button1Mask << (lisp_event->event.button.button-1);
1422 x_event.xbutton.state = state;
1423 x_event.xbutton.button = lisp_event->event.button.button;
1424 x_event.xkey.same_screen = True;
1426 DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len);
1430 /* the next thing blocks everything... */
1431 if (DndHandleDragging(wid, &x_event))
1437 #endif /* HAVE_OFFIX_DND */
1440 /************************************************************************/
1441 /* widget creation */
1442 /************************************************************************/
1444 /* The widget hierarchy is
1446 argv[0] shell container FRAME-NAME
1447 ApplicationShell EmacsShell EmacsManager EmacsFrame
1449 We accept geometry specs in this order:
1451 *FRAME-NAME.geometry
1452 *EmacsFrame.geometry
1455 Other possibilities for widget hierarchies might be
1457 argv[0] frame container FRAME-NAME
1458 ApplicationShell EmacsShell EmacsManager EmacsFrame
1460 argv[0] FRAME-NAME container FRAME-NAME
1461 ApplicationShell EmacsShell EmacsManager EmacsFrame
1463 argv[0] FRAME-NAME container emacsTextPane
1464 ApplicationShell EmacsShell EmacsManager EmacsFrame
1466 #ifdef EXTERNAL_WIDGET
1467 The ExternalShell widget is simply a replacement for the Shell widget
1468 which is able to deal with using an externally-supplied window instead
1469 of always creating its own.
1474 #ifdef EXTERNAL_WIDGET
1477 is_valid_window (Window w, struct device *d)
1479 XWindowAttributes xwa;
1480 Display *dpy = DEVICE_X_DISPLAY (d);
1482 expect_x_error (dpy);
1483 XGetWindowAttributes (dpy, w, &xwa);
1484 return !x_error_occurred_p (dpy);
1487 #endif /* EXTERNAL_WIDGET */
1489 /* This sends a synthetic mouse-motion event to the frame, if the mouse
1490 is over the frame. This ensures that the cursor gets set properly
1491 before the user moves the mouse for the first time. */
1494 x_send_synthetic_mouse_event (struct frame *f)
1496 /* #### write this function. */
1500 first_x_frame_p (struct frame *f)
1502 Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
1503 while (!NILP (rest) &&
1504 (f == XFRAME (XCAR (rest)) ||
1505 !FRAME_X_P (XFRAME (XCAR (rest)))))
1510 /* Figure out what size the EmacsFrame widget should initially be,
1511 and set it. Should be called after the default font has been
1512 determined but before the widget has been realized. */
1515 x_initialize_frame_size (struct frame *f)
1517 /* Geometry of the AppShell */
1521 unsigned int app_w = 0;
1522 unsigned int app_h = 0;
1524 /* Geometry of the EmacsFrame */
1525 int frame_flags = 0;
1528 unsigned int frame_w = 0;
1529 unsigned int frame_h = 0;
1531 /* Hairily merged geometry */
1534 unsigned int w = 80;
1535 unsigned int h = 40;
1538 char *geom = 0, *ew_geom = 0;
1539 Boolean iconic_p = False, ew_iconic_p = False;
1541 Widget wmshell = FRAME_X_SHELL_WIDGET (f);
1542 /* #### This may not be an ApplicationShell any more, with the 'popup
1544 Widget app_shell = XtParent (wmshell);
1545 Widget ew = FRAME_X_TEXT_WIDGET (f);
1547 /* set the position of the frame's root window now. When the
1548 frame was created, the position was initialized to (0,0). */
1550 struct window *win = XWINDOW (f->root_window);
1552 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f)
1553 + FRAME_LEFT_GUTTER_BOUNDS (f);
1554 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f)
1555 + FRAME_TOP_GUTTER_BOUNDS (f);
1557 if (!NILP (f->minibuffer_window))
1559 win = XWINDOW (f->minibuffer_window);
1560 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f)
1561 + FRAME_LEFT_GUTTER_BOUNDS (f);
1565 #ifdef EXTERNAL_WIDGET
1566 /* If we're an external widget, then the size of the frame is predetermined
1567 (by the client) and is not our decision to make. */
1568 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1573 /* #### this junk has not been tested; therefore it's
1574 probably wrong. Doesn't really matter at this point because
1575 currently all frames are either top-level or external widgets. */
1577 /* If we're not our own top-level window, then we shouldn't go messing around
1578 with top-level shells or "Emacs.geometry" or any such stuff. Therefore,
1579 we do as follows to determine the size of the frame:
1581 1) If a value for the frame's "geometry" resource was specified, then
1582 use it. (This specifies a size in characters.)
1583 2) Else, if the "width" and "height" resources were specified, then
1584 leave them alone. (This is a value in pixels. Sorry, we can't break
1585 Xt conventions here.)
1586 3) Else, assume a size of 64x12. (This is somewhat arbitrary, but
1587 it's unlikely that a size of 80x40 is desirable because we're probably
1588 inside of a dialog box.)
1590 Set the widget's x, y, height, and width as determined. Don't set the
1591 top-level container widget, because we don't necessarily know what it
1592 is. (Assume it is smart and pays attention to our values.)
1595 if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
1597 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1599 frame_flags = XParseGeometry (ew_geom,
1601 &frame_w, &frame_h);
1602 if (! (frame_flags & (WidthValue | HeightValue)))
1605 XtSetArg (al [0], XtNwidth, &frame_w);
1606 XtSetArg (al [1], XtNheight, &frame_h);
1607 XtGetValues (ew, al, 2);
1608 if (!frame_w && !frame_h)
1612 frame_flags |= WidthValue | HeightValue;
1615 if (frame_flags & (WidthValue | HeightValue))
1616 EmacsFrameSetCharSize (ew, frame_w, frame_h);
1617 if (frame_flags & (XValue | YValue))
1620 XtSetArg (al [0], XtNwidth, &frame_w);
1621 XtSetArg (al [1], XtNheight, &frame_h);
1622 XtGetValues (ew, al, 2);
1624 if (frame_flags & XNegative)
1626 if (frame_flags & YNegative)
1629 XtSetArg (al [0], XtNx, frame_x);
1630 XtSetArg (al [1], XtNy, frame_y);
1631 XtSetValues (ew, al, 2);
1637 /* OK, we're a top-level shell. */
1639 if (!XtIsWMShell (wmshell))
1642 /* If the EmacsFrame doesn't have a geometry but the shell does,
1643 treat that as the geometry of the frame.
1644 (Is this bogus? I'm not sure.) */
1646 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1649 Xt_GET_VALUE (wmshell, XtNgeometry, &geom);
1653 Xt_SET_VALUE (ew, XtNgeometry, ew_geom);
1657 /* If the Shell is iconic, then the EmacsFrame is iconic.
1658 (Is this bogus? I'm not sure.) */
1659 Xt_GET_VALUE (ew, XtNiconic, &ew_iconic_p);
1662 Xt_GET_VALUE (wmshell, XtNiconic, &iconic_p);
1665 ew_iconic_p = iconic_p;
1666 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1670 Xt_GET_VALUE (app_shell, XtNgeometry, &geom);
1672 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
1675 frame_flags = XParseGeometry (ew_geom,
1677 &frame_w, &frame_h);
1679 if (first_x_frame_p (f))
1681 /* If this is the first frame created:
1682 ====================================
1684 - Use the ApplicationShell's size/position, if specified.
1685 (This is "Emacs.geometry", or the "-geometry" command line arg.)
1686 - Else use the EmacsFrame's size/position.
1687 (This is "*FRAME-NAME.geometry")
1689 - If the AppShell is iconic, the frame should be iconic.
1691 AppShell comes first so that -geometry always applies to the first
1692 frame created, even if there is an "every frame" entry in the
1695 if (app_flags & (XValue | YValue))
1697 x = app_x; y = app_y;
1698 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
1700 else if (frame_flags & (XValue | YValue))
1702 x = frame_x; y = frame_y;
1703 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1706 if (app_flags & (WidthValue | HeightValue))
1708 w = app_w; h = app_h;
1709 flags |= (app_flags & (WidthValue | HeightValue));
1711 else if (frame_flags & (WidthValue | HeightValue))
1713 w = frame_w; h = frame_h;
1714 flags |= (frame_flags & (WidthValue | HeightValue));
1717 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
1720 Xt_GET_VALUE (app_shell, XtNiconic, &iconic_p);
1723 ew_iconic_p = iconic_p;
1724 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1730 /* If this is not the first frame created:
1731 ========================================
1733 - use the EmacsFrame's size/position if specified
1734 - Otherwise, use the ApplicationShell's size, but not position.
1736 So that means that one can specify the position of the first frame
1737 with "Emacs.geometry" or `-geometry'; but can only specify the
1738 position of subsequent frames with "*FRAME-NAME.geometry".
1740 AppShell comes second so that -geometry does not apply to subsequent
1741 frames when there is an "every frame" entry in the resource db,
1742 but does apply to the first frame.
1744 if (frame_flags & (XValue | YValue))
1746 x = frame_x; y = frame_y;
1747 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1750 if (frame_flags & (WidthValue | HeightValue))
1752 w = frame_w; h = frame_h;
1753 flags |= (frame_flags & (WidthValue | HeightValue));
1755 else if (app_flags & (WidthValue | HeightValue))
1759 flags |= (app_flags & (WidthValue | HeightValue));
1763 x_set_initial_frame_size (f, flags, x, y, w, h);
1767 x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
1771 /* compute height of all top-area widgets */
1772 for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1774 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1775 if (wid && XtIsManaged (wid))
1776 *topbreadth += wid->core.height + 2*wid->core.border_width;
1781 x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
1783 struct frame *f = (struct frame *) client_data;
1784 EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
1785 Dimension width = emst->width;
1786 Dimension height = emst->height;
1787 Widget text = FRAME_X_TEXT_WIDGET (f);
1788 Dimension textbord = text->core.border_width;
1789 Dimension topbreadth;
1790 Position text_x = 0, text_y = 0;
1793 x_get_layout_sizes (f, &topbreadth);
1795 /* first the menubar and psheets ... */
1796 for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1798 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1799 if (wid && XtIsManaged (wid))
1801 Dimension bord = wid->core.border_width;
1802 XtConfigureWidget (wid, 0, text_y,
1803 width - 2*bord, wid->core.height,
1805 text_y += wid->core.height + 2*bord;
1809 #ifdef HAVE_SCROLLBARS
1810 f->scrollbar_y_offset = topbreadth + textbord;
1813 /* finally the text area */
1814 XtConfigureWidget (text, text_x, text_y,
1816 height - text_y - 2*textbord,
1821 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1823 struct frame *f = (struct frame *) client_data;
1824 EmacsManagerQueryGeometryStruct *emst =
1825 (EmacsManagerQueryGeometryStruct *) call_data;
1826 Widget text = FRAME_X_TEXT_WIDGET (f);
1827 Dimension textbord = text->core.border_width;
1828 Dimension topbreadth;
1829 XtWidgetGeometry req, repl;
1830 int mask = emst->request_mode & (CWWidth | CWHeight);
1832 x_get_layout_sizes (f, &topbreadth);
1834 /* Strip away menubar from suggested size, and ask the text widget
1835 what size it wants to be. */
1836 req.request_mode = mask;
1838 req.width = emst->proposed_width - 2*textbord;
1839 if (mask & CWHeight)
1840 req.height = emst->proposed_height - topbreadth - 2*textbord;
1841 XtQueryGeometry (text, &req, &repl);
1843 /* Now add the menubar back again */
1844 emst->proposed_width = repl.width + 2*textbord;
1845 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1848 /* Creates the widgets for a frame.
1849 lisp_window_id is a Lisp description of an X window or Xt
1852 This function does not create or map the windows. (That is
1853 done by x_popup_frame().)
1856 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1859 struct device *d = XDEVICE (f->device);
1860 Visual *visual = DEVICE_X_VISUAL (d);
1861 int depth = DEVICE_X_DEPTH (d);
1862 Colormap cmap = DEVICE_X_COLORMAP (d);
1863 #ifdef EXTERNAL_WIDGET
1864 Window window_id = 0;
1869 Widget text, container, shell;
1870 Widget parentwid = 0;
1871 #ifdef HAVE_MENUBARS
1872 int menubar_visible;
1876 if (STRINGP (f->name))
1877 LISP_STRING_TO_EXTERNAL (f->name, name, Qctext);
1881 /* The widget hierarchy is
1883 argv[0] shell pane FRAME-NAME
1884 ApplicationShell EmacsShell EmacsManager EmacsFrame
1886 (the type of the shell is ExternalShell if this frame is running
1887 in another client's window)
1889 However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
1890 Normally such shells have name/class shellname/appclass, which in this
1891 case would be "shell/Emacs" instead of "frame-name/Emacs". We could
1892 also get around this by naming the shell "frame-name", but that would
1893 be confusing because the text area (the EmacsFrame widget inferior of
1894 the shell) is also called that. So we just set the WM_CLASS property.
1897 #ifndef EXTERNAL_WIDGET
1898 if (!NILP (lisp_window_id))
1899 error ("support for external widgets was not enabled at compile-time");
1901 if (!NILP (lisp_window_id))
1905 CHECK_STRING (lisp_window_id);
1906 string = (char *) XSTRING_DATA (lisp_window_id);
1907 if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
1908 sscanf (string+2, "%lxu", &window_id);
1910 else if (string[0] == 'w')
1912 sscanf (string+1, "%x", &parent_widget);
1914 window_id = XtWindow (parent_widget);
1918 sscanf (string, "%lu", &window_id);
1919 if (!is_valid_window (window_id, d))
1920 error ("Invalid window %lu", (unsigned long) window_id);
1921 FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
1923 #endif /* EXTERNAL_WIDGET */
1924 FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
1927 XtSetArg (al[ac], XtNallowShellResize, True); ac++;
1928 #ifdef LWLIB_USES_MOTIF
1929 /* Motif sucks beans. Without this in here, it will delete the window
1930 out from under us when it receives a WM_DESTROY_WINDOW message
1932 XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1935 #ifdef EXTERNAL_WIDGET
1938 XtSetArg (al[ac], XtNwindow, window_id); ac++;
1941 #endif /* EXTERNAL_WIDGET */
1943 XtSetArg (al[ac], XtNinput, True); ac++;
1944 XtSetArg (al[ac], XtNminWidthCells, 10); ac++;
1945 XtSetArg (al[ac], XtNminHeightCells, 1); ac++;
1946 XtSetArg (al[ac], XtNvisual, visual); ac++;
1947 XtSetArg (al[ac], XtNdepth, depth); ac++;
1948 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1953 parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
1954 XtSetArg (al[ac], XtNtransientFor, parentwid); ac++;
1957 shell = XtCreatePopupShell ("shell",
1959 #ifdef EXTERNAL_WIDGET
1960 window_id ? externalShellWidgetClass :
1962 parentwid ? transientEmacsShellWidgetClass :
1963 topLevelEmacsShellWidgetClass
1965 parentwid ? parentwid :
1966 DEVICE_XT_APP_SHELL (d),
1968 FRAME_X_SHELL_WIDGET (f) = shell;
1969 maybe_set_frame_title_format (shell);
1971 /* Create the manager widget */
1973 XtSetArg (al[ac], XtNvisual, visual); ac++;
1974 XtSetArg (al[ac], XtNdepth, depth); ac++;
1975 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1977 container = XtCreateWidget ("container",
1978 emacsManagerWidgetClass, shell, al, ac);
1979 FRAME_X_CONTAINER_WIDGET (f) = container;
1980 XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
1982 XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
1985 /* Create the text area */
1987 XtSetArg (al[ac], XtNvisual, visual); ac++;
1988 XtSetArg (al[ac], XtNdepth, depth); ac++;
1989 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1990 XtSetArg (al[ac], XtNborderWidth, 0); ac++; /* should this be settable? */
1991 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
1992 text = XtCreateWidget (name, emacsFrameClass, container, al, ac);
1993 FRAME_X_TEXT_WIDGET (f) = text;
1995 #ifdef HAVE_MENUBARS
1996 /* Create the initial menubar widget. */
1997 menubar_visible = x_initialize_frame_menubar (f);
1998 FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
1999 FRAME_X_NUM_TOP_WIDGETS (f) = 1;
2001 if (menubar_visible)
2002 XtManageChild (menubar);
2003 #endif /* HAVE_MENUBARS */
2004 XtManageChild (text);
2005 XtManageChild (container);
2008 /* We used to call XtPopup() in x_popup_frame, but that doesn't give
2009 you control over whether the widget is initially mapped or not
2010 because XtPopup() makes an unconditional call to XMapRaised().
2011 Boy, those Xt designers were clever.
2013 When we first removed it we only kept the XtRealizeWidget call in
2014 XtPopup. For everything except HP's that was enough. For HP's,
2015 though, the failure to call the popup callbacks resulted in XEmacs
2016 not accepting any input. Bizarre but true. Stupid but true.
2018 So, in case there are any other gotchas floating out there along
2019 the same lines I've duplicated the majority of XtPopup here. It
2020 assumes no grabs and that the widget is not already popped up, both
2021 valid assumptions for the one place this is called from. */
2023 xemacs_XtPopup (Widget widget)
2025 ShellWidget shell_widget = (ShellWidget) widget;
2026 XtGrabKind call_data = XtGrabNone;
2028 XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data);
2030 shell_widget->shell.popped_up = TRUE;
2031 shell_widget->shell.grab_kind = XtGrabNone;
2032 shell_widget->shell.spring_loaded = False;
2034 if (shell_widget->shell.create_popup_child_proc != NULL)
2035 (*(shell_widget->shell.create_popup_child_proc))(widget);
2037 /* The XtSetValues below are not in XtPopup menu. We just want to
2038 make absolutely sure... */
2039 Xt_SET_VALUE (widget, XtNmappedWhenManaged, False);
2040 XtRealizeWidget (widget);
2041 Xt_SET_VALUE (widget, XtNmappedWhenManaged, True);
2044 /* create the windows for the specified frame and display them.
2045 Note that the widgets have already been created, and any
2046 necessary geometry calculations have already been done. */
2048 x_popup_frame (struct frame *f)
2050 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
2051 Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
2052 struct device *d = XDEVICE (FRAME_DEVICE (f));
2054 /* Before mapping the window, make sure that the WMShell's notion of
2055 whether it should be iconified is synchronized with the EmacsFrame's
2058 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2059 x_wm_set_shell_iconic_p (shell_widget,
2060 ((EmacsFrame) frame_widget)
2061 ->emacs_frame.iconic);
2063 xemacs_XtPopup (shell_widget);
2065 if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
2066 XtMapWidget (shell_widget);
2069 /* We may have set f->visible to 1 in x_init_frame(), so undo
2071 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
2075 #ifdef EXTERNAL_WIDGET
2076 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2077 ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
2080 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2082 /* tell the window manager about us. */
2083 x_wm_store_class_hints (shell_widget, XtName (frame_widget));
2085 #ifndef HAVE_WMCOMMAND
2086 x_wm_maybe_store_wm_command (f);
2087 #endif /* HAVE_WMCOMMAND */
2089 x_wm_hack_wm_protocols (shell_widget);
2094 #endif /* HAVE_XIM */
2097 /* Allow XEmacs to respond to EditRes requests. See the O'Reilly Xt */
2098 /* Intrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
2100 XtAddEventHandler (shell_widget, /* the shell widget in question */
2101 (EventMask) NoEventMask,/* OR with existing mask */
2102 True, /* called on non-maskable events? */
2103 (XtEventHandler) _XEditResCheckMessages, /* the handler */
2105 #endif /* HACK_EDITRES */
2109 XtCallbackRec dnd_transfer_cb_rec[2];
2111 dnd_transfer_cb_rec[0].callback = x_cde_transfer_callback;
2112 dnd_transfer_cb_rec[0].closure = (XtPointer) f;
2113 dnd_transfer_cb_rec[1].callback = NULL;
2114 dnd_transfer_cb_rec[1].closure = NULL;
2116 DtDndVaDropRegister (FRAME_X_TEXT_WIDGET (f),
2117 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
2118 XmDROP_COPY, dnd_transfer_cb_rec,
2119 DtNtextIsBuffer, True,
2120 DtNregisterChildren, True,
2121 DtNpreserveRegistration, False,
2124 #endif /* HAVE_CDE */
2126 /* Do a stupid property change to force the server to generate a
2127 propertyNotify event so that the event_stream server timestamp will
2128 be initialized to something relevant to the time we created the window.
2130 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2131 DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
2132 (unsigned char*) NULL, 0);
2134 x_send_synthetic_mouse_event (f);
2138 allocate_x_frame_struct (struct frame *f)
2140 /* zero out all slots. */
2141 f->frame_data = xnew_and_zero (struct x_frame);
2143 /* yeah, except the lisp ones */
2144 FRAME_X_ICON_PIXMAP (f) = Qnil;
2145 FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
2149 /************************************************************************/
2150 /* Lisp functions */
2151 /************************************************************************/
2154 x_init_frame_1 (struct frame *f, Lisp_Object props)
2156 /* This function can GC */
2157 Lisp_Object device = FRAME_DEVICE (f);
2158 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
2159 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
2164 popup = Fselected_frame (device);
2165 CHECK_LIVE_FRAME (popup);
2166 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
2167 signal_simple_error_2 ("Parent must be on same device as frame",
2172 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
2173 * to make sure that messages were displayed as soon as possible
2174 * if we're creating the first frame on a device. But it is
2175 * better to just set this all the time, so that when a new frame
2176 * is created that covers the selected frame, echo area status
2177 * messages can still be seen. f->visible is reset later if the
2178 * initially-unmapped property is found to be non-nil in the
2183 allocate_x_frame_struct (f);
2184 x_create_widgets (f, lisp_window_id, popup);
2188 x_init_frame_2 (struct frame *f, Lisp_Object props)
2190 /* Set up the values of the widget/frame. A case could be made for putting
2191 this inside of the widget's initialize method. */
2193 update_frame_face_values (f);
2194 x_initialize_frame_size (f);
2196 * update_frame_title() can't be done here, because some of the
2197 * modeline specs depend on the frame's device having a selected
2198 * frame, and that may not have been set up yet. The redisplay
2199 * will update the frame title anyway, so nothing is lost.
2201 * It turns out it gives problems with FVWMs name based mapping.
2202 * We'll just need to be careful in the modeline specs.
2204 update_frame_title (f);
2208 x_init_frame_3 (struct frame *f)
2210 /* Pop up the frame. */
2216 x_mark_frame (struct frame *f)
2218 mark_object (FRAME_X_ICON_PIXMAP (f));
2219 mark_object (FRAME_X_ICON_PIXMAP_MASK (f));
2223 x_set_frame_icon (struct frame *f)
2225 Pixmap x_pixmap, x_mask;
2227 if (IMAGE_INSTANCEP (f->icon)
2228 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
2230 x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (f->icon);
2231 x_mask = XIMAGE_INSTANCE_X_MASK (f->icon);
2239 /* Store the X data into the widget. */
2242 XtSetArg (al [0], XtNiconPixmap, x_pixmap);
2243 XtSetArg (al [1], XtNiconMask, x_mask);
2244 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
2249 x_set_frame_pointer (struct frame *f)
2251 XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
2252 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2253 XIMAGE_INSTANCE_X_CURSOR (f->pointer));
2254 XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
2258 x_get_frame_parent (struct frame *f)
2260 Widget parentwid = 0;
2262 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNtransientFor, &parentwid);
2263 /* find the frame whose wid is parentwid */
2266 Lisp_Object frmcons;
2267 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
2269 Lisp_Object frame = XCAR (frmcons);
2270 if (FRAME_X_SHELL_WIDGET (XFRAME (frame)) == parentwid)
2277 DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
2278 Get the ID of the X11 window.
2279 This gives us a chance to manipulate the Emacs window from within a
2280 different program. Since the ID is an unsigned long, we return it as
2286 struct frame *f = decode_x_frame (frame);
2288 sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
2289 return build_string (str);
2293 /************************************************************************/
2294 /* manipulating the X window */
2295 /************************************************************************/
2298 x_set_frame_position (struct frame *f, int xoff, int yoff)
2300 Widget w = FRAME_X_SHELL_WIDGET (f);
2301 Display *dpy = XtDisplay (w);
2302 Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
2303 Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
2304 Dimension shell_w, shell_h, shell_bord;
2308 XtSetArg (al [0], XtNwidth, &shell_w);
2309 XtSetArg (al [1], XtNheight, &shell_h);
2310 XtSetArg (al [2], XtNborderWidth, &shell_bord);
2311 XtGetValues (w, al, 3);
2314 xoff >= 0 && yoff >= 0 ? NorthWestGravity :
2315 xoff >= 0 ? SouthWestGravity :
2316 yoff >= 0 ? NorthEastGravity :
2319 xoff += frame_w - shell_w - 2*shell_bord;
2321 yoff += frame_h - shell_h - 2*shell_bord;
2323 /* Update the hints so that, if this window is currently iconified, it will
2324 come back at the right place. We can't look at s->visible to determine
2325 whether it is iconified because it might not be up-to-date yet (the queue
2326 might not be processed). */
2327 XtSetArg (al [0], XtNwinGravity, win_gravity);
2328 XtSetArg (al [1], XtNx, xoff);
2329 XtSetArg (al [2], XtNy, yoff);
2330 XtSetValues (w, al, 3);
2332 /* Sometimes you will find that
2334 (set-frame-position (selected-frame) -50 -50)
2336 doesn't put the frame where you expect it to: i.e. it's closer to
2337 the lower-right corner than it should be, and it appears that the
2338 size of the WM decorations was not taken into account. This is
2339 *not* a problem with this function. Both mwm and twm have bugs
2340 in handling this situation. (mwm ignores the window gravity and
2341 always assumes NorthWest, except the first time you map the
2342 window; twm gets things almost right, but forgets to account for
2343 the border width of the top-level window.) This function does
2344 what it's supposed to according to the ICCCM, and I'm not about
2345 to hack around window-manager bugs. */
2348 /* This is not necessary under either mwm or twm */
2349 x_wm_mark_shell_position_user_specified (w);
2353 /* Call this to change the size of frame S's x-window. */
2356 x_set_frame_size (struct frame *f, int cols, int rows)
2358 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
2360 /* this is not correct. x_set_frame_size() is called from
2361 Fset_frame_size(), which may or may not have been called
2362 by the user (e.g. update_EmacsFrame() calls it when the font
2363 changes). For now, don't bother with getting this right. */
2364 x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
2369 x_set_mouse_position (struct window *w, int x, int y)
2371 struct frame *f = XFRAME (w->frame);
2373 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2374 XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
2375 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
2379 x_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
2381 Display *display = DEVICE_X_DISPLAY (d);
2382 Window child_window;
2387 unsigned int keys_and_buttons;
2390 if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
2391 &root_window, &child_window, &root_x, &root_y,
2392 &win_x, &win_y, &keys_and_buttons) == False)
2395 if (child_window == None)
2396 return 0; /* not over any window. */
2401 if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
2402 &win_x, &win_y, &child_window) == False)
2406 if (child_window == None)
2410 /* At this point, win is the innermost window containing the pointer
2411 and win_x and win_y are the coordinates of that window. */
2412 f = x_any_window_to_frame (d, win);
2415 XSETFRAME (*frame, f);
2417 if (XTranslateCoordinates (display, win,
2418 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2419 win_x, win_y, x, y, &child_window) == False)
2427 x_cant_notify_wm_error (void)
2429 error ("Can't notify window manager of iconification.");
2432 /* Raise frame F. */
2434 x_raise_frame_1 (struct frame *f, int force)
2436 if (FRAME_VISIBLE_P (f) || force)
2438 Widget bottom_dialog;
2441 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2442 Window emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
2444 /* first raises all the dialog boxes, then put emacs just below the
2445 * bottom most dialog box */
2446 bottom_dialog = lw_raise_all_pop_up_widgets ();
2447 if (bottom_dialog && XtWindow (bottom_dialog))
2449 xwc.sibling = XtWindow (bottom_dialog);
2450 xwc.stack_mode = Below;
2451 flags = CWSibling | CWStackMode;
2455 xwc.stack_mode = Above;
2456 flags = CWStackMode;
2459 if (!XReconfigureWMWindow (display, emacs_window,
2460 DefaultScreen (display),
2462 x_cant_notify_wm_error ();
2467 x_raise_frame (struct frame *f)
2469 x_raise_frame_1 (f, 1);
2472 /* Lower frame F. */
2474 x_lower_frame (struct frame *f)
2476 if (FRAME_VISIBLE_P (f))
2478 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2480 unsigned int flags = CWStackMode;
2482 xwc.stack_mode = Below;
2483 if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
2484 DefaultScreen (display), flags, &xwc))
2485 x_cant_notify_wm_error ();
2490 x_enable_frame (struct frame *f)
2492 XtSetSensitive (FRAME_X_SHELL_WIDGET (f), True);
2496 x_disable_frame (struct frame *f)
2498 XtSetSensitive (FRAME_X_SHELL_WIDGET (f), False);
2501 /* Change from withdrawn state to mapped state. */
2503 x_make_frame_visible (struct frame *f)
2505 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2507 if (!FRAME_VISIBLE_P(f))
2508 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2510 x_raise_frame_1 (f, 0);
2513 /* Change from mapped state to withdrawn state. */
2515 x_make_frame_invisible (struct frame *f)
2517 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2519 if (!FRAME_VISIBLE_P(f))
2522 if (!XWithdrawWindow (display,
2523 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2524 DefaultScreen (display)))
2525 x_cant_notify_wm_error ();
2529 x_frame_visible_p (struct frame *f)
2532 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2533 XWindowAttributes xwa;
2537 This is bad, very bad :-(
2538 It is not compatible with our tristate visible and
2539 it should never ever change the visibility for us, this leads to
2540 the frame-freeze problem under fvwm because with the pager
2542 Mappedness != Viewability != Visibility != Emacs f->visible
2544 This first unequalness is the reason for the frame freezing problem
2545 under fvwm (it happens when the frame is another fvwm-page)
2547 The second unequalness happen when it is on the same fvwm-page
2548 but in an invisible part of the visible screen.
2550 For now we just return the XEmacs internal value --- which might not be up
2551 to date. Is that a problem? ---. Otherwise we should
2552 use async visibility like in standard Emacs.
2555 if (!XGetWindowAttributes (display,
2556 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2560 result = xwa.map_state == IsViewable;
2561 /* In this implementation it should at least be != IsUnmapped
2564 f->visible = result;
2572 x_frame_totally_visible_p (struct frame *f)
2574 return FRAME_X_TOTALLY_VISIBLE_P (f);
2577 /* Change window state from mapped to iconified. */
2579 x_iconify_frame (struct frame *f)
2581 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2583 if (!XIconifyWindow (display,
2584 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2585 DefaultScreen (display)))
2586 x_cant_notify_wm_error ();
2591 /* Sets the X focus to frame f. */
2593 x_focus_on_frame (struct frame *f)
2595 XWindowAttributes xwa;
2596 Widget shell_widget;
2599 assert (FRAME_X_P (f));
2601 shell_widget = FRAME_X_SHELL_WIDGET (f);
2602 if (!XtWindow (shell_widget))
2605 #ifdef EXTERNAL_WIDGET
2606 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2607 ExternalShellSetFocus (shell_widget);
2608 #endif /* EXTERNAL_WIDGET */
2610 /* Do the ICCCM focus change if the window is still visible.
2611 The s->visible flag might not be up-to-date, because we might
2612 not have processed magic events recently. So make a server
2613 round-trip to find out whether it's really mapped right now.
2614 We grab the server to do this, because that's the only way to
2615 eliminate the race condition.
2617 XGrabServer (XtDisplay (shell_widget));
2618 if (XGetWindowAttributes (XtDisplay (shell_widget),
2619 XtWindow (shell_widget),
2621 /* JV: it is bad to change the visibility like this, so we don't for the
2622 moment, at least change_frame_visibility should be called
2623 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2624 but still X-invisible
2625 f->visible = xwa.map_state == IsViewable; */
2626 viewable = xwa.map_state == IsViewable;
2633 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2634 /* Don't explicitly set the focus on this window unless the focus
2635 was on some other window (not PointerRoot). Note that, even when
2636 running a point-to-type window manager like *twm, there is always
2637 a focus window; the window manager maintains that based on the
2638 mouse position. If you set the "NoTitleFocus" option in these
2639 window managers, then the server itself maintains the focus via
2640 PointerRoot, and changing that to focus on the window would make
2641 the window grab the focus. Very bad.
2643 if (focus != PointerRoot)
2645 XSetInputFocus (XtDisplay (shell_widget),
2646 XtWindow (shell_widget),
2648 DEVICE_X_MOUSE_TIMESTAMP
2649 (XDEVICE (FRAME_DEVICE (f))));
2650 XFlush (XtDisplay (shell_widget));
2653 XUngrabServer (XtDisplay (shell_widget));
2654 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2657 /* Destroy the X window of frame F. */
2659 x_delete_frame (struct frame *f)
2663 #ifndef HAVE_WMCOMMAND
2664 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2665 x_wm_maybe_move_wm_command (f);
2666 #endif /* HAVE_WMCOMMAND */
2669 DtDndDropUnregister (FRAME_X_TEXT_WIDGET (f));
2670 #endif /* HAVE_CDE */
2672 assert (FRAME_X_SHELL_WIDGET (f) != 0);
2673 dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
2675 #ifdef EXTERNAL_WIDGET
2676 expect_x_error (dpy);
2677 /* for obscure reasons having (I think) to do with the internal
2678 window-to-widget hierarchy maintained by Xt, we have to call
2679 XtUnrealizeWidget() here. Xt can really suck. */
2680 if (f->being_deleted)
2681 XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
2682 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2683 x_error_occurred_p (dpy);
2685 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2686 /* make sure the windows are really gone! */
2687 /* #### Is this REALLY necessary? */
2689 #endif /* EXTERNAL_WIDGET */
2691 FRAME_X_SHELL_WIDGET (f) = 0;
2693 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2695 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2696 FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0;
2701 xfree (f->frame_data);
2707 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2713 XSETFRAME(frame, frm);
2715 if (EQ (name, Qforeground))
2717 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2720 if (!EQ (color, Vthe_null_color_instance))
2722 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2723 XtSetArg (al[ac], XtNforeground, (void *) fgc.pixel); ac++;
2726 else if (EQ (name, Qbackground))
2728 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2731 if (!EQ (color, Vthe_null_color_instance))
2733 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2734 XtSetArg (al[ac], XtNbackground, (void *) bgc.pixel); ac++;
2737 /* Really crappy way to force the modeline shadows to be
2738 redrawn. But effective. */
2739 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2740 MARK_FRAME_CHANGED (frm);
2742 else if (EQ (name, Qfont))
2744 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2746 if (!EQ (font, Vthe_null_font_instance))
2747 XtSetArg (al[ac], XtNfont,
2748 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2754 XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
2756 #ifdef HAVE_TOOLBARS
2757 /* Setting the background clears the entire frame area
2758 including the toolbar so we force an immediate redraw of
2760 if (EQ (name, Qbackground))
2761 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2762 #endif /* HAVE_TOOLBARS */
2764 /* Set window manager resize increment hints according to
2765 the new character size */
2766 if (EQ (name, Qfont))
2767 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2771 /************************************************************************/
2772 /* initialization */
2773 /************************************************************************/
2776 syms_of_frame_x (void)
2778 defsymbol (&Qwindow_id, "window-id");
2779 defsymbol (&Qx_resource_name, "x-resource-name");
2781 DEFSUBR (Fx_window_id);
2783 DEFSUBR (Fcde_start_drag_internal);
2785 #ifdef HAVE_OFFIX_DND
2786 DEFSUBR (Foffix_start_drag_internal);
2791 console_type_create_frame_x (void)
2794 CONSOLE_HAS_METHOD (x, init_frame_1);
2795 CONSOLE_HAS_METHOD (x, init_frame_2);
2796 CONSOLE_HAS_METHOD (x, init_frame_3);
2797 CONSOLE_HAS_METHOD (x, mark_frame);
2798 CONSOLE_HAS_METHOD (x, focus_on_frame);
2799 CONSOLE_HAS_METHOD (x, delete_frame);
2800 CONSOLE_HAS_METHOD (x, get_mouse_position);
2801 CONSOLE_HAS_METHOD (x, set_mouse_position);
2802 CONSOLE_HAS_METHOD (x, raise_frame);
2803 CONSOLE_HAS_METHOD (x, lower_frame);
2804 CONSOLE_HAS_METHOD (x, enable_frame);
2805 CONSOLE_HAS_METHOD (x, disable_frame);
2806 CONSOLE_HAS_METHOD (x, make_frame_visible);
2807 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2808 CONSOLE_HAS_METHOD (x, iconify_frame);
2809 CONSOLE_HAS_METHOD (x, set_frame_size);
2810 CONSOLE_HAS_METHOD (x, set_frame_position);
2811 CONSOLE_HAS_METHOD (x, frame_property);
2812 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2813 CONSOLE_HAS_METHOD (x, frame_properties);
2814 CONSOLE_HAS_METHOD (x, set_frame_properties);
2815 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2816 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2817 CONSOLE_HAS_METHOD (x, frame_visible_p);
2818 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2819 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2820 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2821 CONSOLE_HAS_METHOD (x, set_frame_icon);
2822 CONSOLE_HAS_METHOD (x, get_frame_parent);
2823 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2827 vars_of_frame_x (void)
2829 #ifdef EXTERNAL_WIDGET
2830 Fprovide (intern ("external-widget"));
2833 /* this call uses only safe functions from emacs.c */
2834 init_x_prop_symbols ();
2836 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2837 Plist of default frame-creation properties for X frames.
2838 These override what is specified in the resource database and in
2839 `default-frame-plist', but are overridden by the arguments to the
2840 particular call to `make-frame'.
2842 Note: In many cases, properties of a frame are available as specifiers
2843 instead of through the frame-properties mechanism.
2845 Here is a list of recognized frame properties, other than those
2846 documented in `set-frame-properties' (they can be queried and
2847 set at any time, except as otherwise noted):
2849 window-id The X window ID corresponding to the
2850 frame. May be set only at startup, and
2851 only if external widget support was
2852 compiled in; doing so causes the frame
2853 to be created as an "external widget"
2854 in another program that uses an existing
2855 window in the program rather than creating
2857 initially-unmapped If non-nil, the frame will not be visible
2858 when it is created. In this case, you
2859 need to call `make-frame-visible' to make
2861 popup If non-nil, it should be a frame, and this
2862 frame will be created as a "popup" frame
2863 whose parent is the given frame. This
2864 will make the window manager treat the
2865 frame as a dialog box, which may entail
2866 doing different things (e.g. not asking
2867 for positioning, and not iconifying
2868 separate from its parent).
2869 inter-line-space Not currently implemented.
2870 toolbar-shadow-thickness Thickness of toolbar shadows.
2871 background-toolbar-color Color of toolbar background.
2872 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2873 (*Not* specific to the bottom-toolbar.)
2874 top-toolbar-shadow-color Color of top shadows on toolbars.
2875 (*Not* specific to the top-toolbar.)
2876 internal-border-width Width of internal border around text area.
2877 border-width Width of external border around text area.
2878 top Y position (in pixels) of the upper-left
2879 outermost corner of the frame (i.e. the
2880 upper-left of the window-manager
2882 left X position (in pixels) of the upper-left
2883 outermost corner of the frame (i.e. the
2884 upper-left of the window-manager
2886 border-color Color of external border around text area.
2887 cursor-color Color of text cursor.
2889 See also `default-frame-plist', which specifies properties which apply
2890 to all frames, not just X frames.
2892 Vdefault_x_frame_plist = Qnil;
2894 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;