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 */
1815 Dimension nw = width - 2*textbord;
1816 Dimension nh = height - text_y - 2*textbord;
1818 if (nh != f->pixheight || nw != f->pixwidth)
1819 MARK_FRAME_SIZE_SLIPPED (f);
1820 XtConfigureWidget (text, text_x, text_y, nw, nh, textbord);
1825 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1827 struct frame *f = (struct frame *) client_data;
1828 EmacsManagerQueryGeometryStruct *emst =
1829 (EmacsManagerQueryGeometryStruct *) call_data;
1830 Widget text = FRAME_X_TEXT_WIDGET (f);
1831 Dimension textbord = text->core.border_width;
1832 Dimension topbreadth;
1833 XtWidgetGeometry req, repl;
1834 int mask = emst->request_mode & (CWWidth | CWHeight);
1836 x_get_layout_sizes (f, &topbreadth);
1838 /* Strip away menubar from suggested size, and ask the text widget
1839 what size it wants to be. */
1840 req.request_mode = mask;
1842 req.width = emst->proposed_width - 2*textbord;
1843 if (mask & CWHeight)
1844 req.height = emst->proposed_height - topbreadth - 2*textbord;
1845 XtQueryGeometry (text, &req, &repl);
1847 /* Now add the menubar back again */
1848 emst->proposed_width = repl.width + 2*textbord;
1849 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1852 /* Creates the widgets for a frame.
1853 lisp_window_id is a Lisp description of an X window or Xt
1856 This function does not create or map the windows. (That is
1857 done by x_popup_frame().)
1860 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1863 struct device *d = XDEVICE (f->device);
1864 Visual *visual = DEVICE_X_VISUAL (d);
1865 int depth = DEVICE_X_DEPTH (d);
1866 Colormap cmap = DEVICE_X_COLORMAP (d);
1867 #ifdef EXTERNAL_WIDGET
1868 Window window_id = 0;
1873 Widget text, container, shell;
1874 Widget parentwid = 0;
1875 #ifdef HAVE_MENUBARS
1876 int menubar_visible;
1880 if (STRINGP (f->name))
1881 LISP_STRING_TO_EXTERNAL (f->name, name, Qctext);
1885 /* The widget hierarchy is
1887 argv[0] shell pane FRAME-NAME
1888 ApplicationShell EmacsShell EmacsManager EmacsFrame
1890 (the type of the shell is ExternalShell if this frame is running
1891 in another client's window)
1893 However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
1894 Normally such shells have name/class shellname/appclass, which in this
1895 case would be "shell/Emacs" instead of "frame-name/Emacs". We could
1896 also get around this by naming the shell "frame-name", but that would
1897 be confusing because the text area (the EmacsFrame widget inferior of
1898 the shell) is also called that. So we just set the WM_CLASS property.
1901 #ifndef EXTERNAL_WIDGET
1902 if (!NILP (lisp_window_id))
1903 error ("support for external widgets was not enabled at compile-time");
1905 if (!NILP (lisp_window_id))
1909 CHECK_STRING (lisp_window_id);
1910 string = (char *) XSTRING_DATA (lisp_window_id);
1911 if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
1912 sscanf (string+2, "%lxu", &window_id);
1914 else if (string[0] == 'w')
1916 sscanf (string+1, "%x", &parent_widget);
1918 window_id = XtWindow (parent_widget);
1922 sscanf (string, "%lu", &window_id);
1923 if (!is_valid_window (window_id, d))
1924 error ("Invalid window %lu", (unsigned long) window_id);
1925 FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
1927 #endif /* EXTERNAL_WIDGET */
1928 FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
1931 XtSetArg (al[ac], XtNallowShellResize, True); ac++;
1932 #ifdef LWLIB_USES_MOTIF
1933 /* Motif sucks beans. Without this in here, it will delete the window
1934 out from under us when it receives a WM_DESTROY_WINDOW message
1936 XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1939 #ifdef EXTERNAL_WIDGET
1942 XtSetArg (al[ac], XtNwindow, window_id); ac++;
1945 #endif /* EXTERNAL_WIDGET */
1947 XtSetArg (al[ac], XtNinput, True); ac++;
1948 XtSetArg (al[ac], XtNminWidthCells, 10); ac++;
1949 XtSetArg (al[ac], XtNminHeightCells, 1); ac++;
1950 XtSetArg (al[ac], XtNvisual, visual); ac++;
1951 XtSetArg (al[ac], XtNdepth, depth); ac++;
1952 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1957 parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
1958 XtSetArg (al[ac], XtNtransientFor, parentwid); ac++;
1961 shell = XtCreatePopupShell ("shell",
1963 #ifdef EXTERNAL_WIDGET
1964 window_id ? externalShellWidgetClass :
1966 parentwid ? transientEmacsShellWidgetClass :
1967 topLevelEmacsShellWidgetClass
1969 parentwid ? parentwid :
1970 DEVICE_XT_APP_SHELL (d),
1972 FRAME_X_SHELL_WIDGET (f) = shell;
1973 maybe_set_frame_title_format (shell);
1975 /* Create the manager widget */
1977 XtSetArg (al[ac], XtNvisual, visual); ac++;
1978 XtSetArg (al[ac], XtNdepth, depth); ac++;
1979 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1981 container = XtCreateWidget ("container",
1982 emacsManagerWidgetClass, shell, al, ac);
1983 FRAME_X_CONTAINER_WIDGET (f) = container;
1984 XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
1986 XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
1989 /* Create the text area */
1991 XtSetArg (al[ac], XtNvisual, visual); ac++;
1992 XtSetArg (al[ac], XtNdepth, depth); ac++;
1993 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1994 XtSetArg (al[ac], XtNborderWidth, 0); ac++; /* should this be settable? */
1995 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
1996 text = XtCreateWidget (name, emacsFrameClass, container, al, ac);
1997 FRAME_X_TEXT_WIDGET (f) = text;
1999 #ifdef HAVE_MENUBARS
2000 /* Create the initial menubar widget. */
2001 menubar_visible = x_initialize_frame_menubar (f);
2002 FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
2003 FRAME_X_NUM_TOP_WIDGETS (f) = 1;
2005 if (menubar_visible)
2006 XtManageChild (menubar);
2007 #endif /* HAVE_MENUBARS */
2008 XtManageChild (text);
2009 XtManageChild (container);
2012 /* We used to call XtPopup() in x_popup_frame, but that doesn't give
2013 you control over whether the widget is initially mapped or not
2014 because XtPopup() makes an unconditional call to XMapRaised().
2015 Boy, those Xt designers were clever.
2017 When we first removed it we only kept the XtRealizeWidget call in
2018 XtPopup. For everything except HP's that was enough. For HP's,
2019 though, the failure to call the popup callbacks resulted in XEmacs
2020 not accepting any input. Bizarre but true. Stupid but true.
2022 So, in case there are any other gotchas floating out there along
2023 the same lines I've duplicated the majority of XtPopup here. It
2024 assumes no grabs and that the widget is not already popped up, both
2025 valid assumptions for the one place this is called from. */
2027 xemacs_XtPopup (Widget widget)
2029 ShellWidget shell_widget = (ShellWidget) widget;
2030 XtGrabKind call_data = XtGrabNone;
2032 XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data);
2034 shell_widget->shell.popped_up = TRUE;
2035 shell_widget->shell.grab_kind = XtGrabNone;
2036 shell_widget->shell.spring_loaded = False;
2038 if (shell_widget->shell.create_popup_child_proc != NULL)
2039 (*(shell_widget->shell.create_popup_child_proc))(widget);
2041 /* The XtSetValues below are not in XtPopup menu. We just want to
2042 make absolutely sure... */
2043 Xt_SET_VALUE (widget, XtNmappedWhenManaged, False);
2044 XtRealizeWidget (widget);
2045 Xt_SET_VALUE (widget, XtNmappedWhenManaged, True);
2048 /* create the windows for the specified frame and display them.
2049 Note that the widgets have already been created, and any
2050 necessary geometry calculations have already been done. */
2052 x_popup_frame (struct frame *f)
2054 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
2055 Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
2056 struct device *d = XDEVICE (FRAME_DEVICE (f));
2058 /* Before mapping the window, make sure that the WMShell's notion of
2059 whether it should be iconified is synchronized with the EmacsFrame's
2062 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2063 x_wm_set_shell_iconic_p (shell_widget,
2064 ((EmacsFrame) frame_widget)
2065 ->emacs_frame.iconic);
2067 xemacs_XtPopup (shell_widget);
2069 if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
2070 XtMapWidget (shell_widget);
2073 /* We may have set f->visible to 1 in x_init_frame(), so undo
2075 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
2079 #ifdef EXTERNAL_WIDGET
2080 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2081 ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
2084 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2086 /* tell the window manager about us. */
2087 x_wm_store_class_hints (shell_widget, XtName (frame_widget));
2089 #ifndef HAVE_WMCOMMAND
2090 x_wm_maybe_store_wm_command (f);
2091 #endif /* HAVE_WMCOMMAND */
2093 x_wm_hack_wm_protocols (shell_widget);
2098 #endif /* HAVE_XIM */
2101 /* Allow XEmacs to respond to EditRes requests. See the O'Reilly Xt */
2102 /* Intrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
2104 XtAddEventHandler (shell_widget, /* the shell widget in question */
2105 (EventMask) NoEventMask,/* OR with existing mask */
2106 True, /* called on non-maskable events? */
2107 (XtEventHandler) _XEditResCheckMessages, /* the handler */
2109 #endif /* HACK_EDITRES */
2113 XtCallbackRec dnd_transfer_cb_rec[2];
2115 dnd_transfer_cb_rec[0].callback = x_cde_transfer_callback;
2116 dnd_transfer_cb_rec[0].closure = (XtPointer) f;
2117 dnd_transfer_cb_rec[1].callback = NULL;
2118 dnd_transfer_cb_rec[1].closure = NULL;
2120 DtDndVaDropRegister (FRAME_X_TEXT_WIDGET (f),
2121 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
2122 XmDROP_COPY, dnd_transfer_cb_rec,
2123 DtNtextIsBuffer, True,
2124 DtNregisterChildren, True,
2125 DtNpreserveRegistration, False,
2128 #endif /* HAVE_CDE */
2130 /* Do a stupid property change to force the server to generate a
2131 propertyNotify event so that the event_stream server timestamp will
2132 be initialized to something relevant to the time we created the window.
2134 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2135 DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
2136 (unsigned char*) NULL, 0);
2138 x_send_synthetic_mouse_event (f);
2142 allocate_x_frame_struct (struct frame *f)
2144 /* zero out all slots. */
2145 f->frame_data = xnew_and_zero (struct x_frame);
2147 /* yeah, except the lisp ones */
2148 FRAME_X_ICON_PIXMAP (f) = Qnil;
2149 FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
2153 /************************************************************************/
2154 /* Lisp functions */
2155 /************************************************************************/
2158 x_init_frame_1 (struct frame *f, Lisp_Object props)
2160 /* This function can GC */
2161 Lisp_Object device = FRAME_DEVICE (f);
2162 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
2163 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
2168 popup = Fselected_frame (device);
2169 CHECK_LIVE_FRAME (popup);
2170 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
2171 signal_simple_error_2 ("Parent must be on same device as frame",
2176 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
2177 * to make sure that messages were displayed as soon as possible
2178 * if we're creating the first frame on a device. But it is
2179 * better to just set this all the time, so that when a new frame
2180 * is created that covers the selected frame, echo area status
2181 * messages can still be seen. f->visible is reset later if the
2182 * initially-unmapped property is found to be non-nil in the
2187 allocate_x_frame_struct (f);
2188 x_create_widgets (f, lisp_window_id, popup);
2192 x_init_frame_2 (struct frame *f, Lisp_Object props)
2194 /* Set up the values of the widget/frame. A case could be made for putting
2195 this inside of the widget's initialize method. */
2197 update_frame_face_values (f);
2198 x_initialize_frame_size (f);
2200 * update_frame_title() can't be done here, because some of the
2201 * modeline specs depend on the frame's device having a selected
2202 * frame, and that may not have been set up yet. The redisplay
2203 * will update the frame title anyway, so nothing is lost.
2205 * It turns out it gives problems with FVWMs name based mapping.
2206 * We'll just need to be careful in the modeline specs.
2208 update_frame_title (f);
2212 x_init_frame_3 (struct frame *f)
2214 /* Pop up the frame. */
2220 x_mark_frame (struct frame *f)
2222 mark_object (FRAME_X_ICON_PIXMAP (f));
2223 mark_object (FRAME_X_ICON_PIXMAP_MASK (f));
2227 x_set_frame_icon (struct frame *f)
2229 Pixmap x_pixmap, x_mask;
2231 if (IMAGE_INSTANCEP (f->icon)
2232 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
2234 x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (f->icon);
2235 x_mask = XIMAGE_INSTANCE_X_MASK (f->icon);
2243 /* Store the X data into the widget. */
2246 XtSetArg (al [0], XtNiconPixmap, x_pixmap);
2247 XtSetArg (al [1], XtNiconMask, x_mask);
2248 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
2253 x_set_frame_pointer (struct frame *f)
2255 XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
2256 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2257 XIMAGE_INSTANCE_X_CURSOR (f->pointer));
2258 XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
2262 x_get_frame_parent (struct frame *f)
2264 Widget parentwid = 0;
2266 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNtransientFor, &parentwid);
2267 /* find the frame whose wid is parentwid */
2270 Lisp_Object frmcons;
2271 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
2273 Lisp_Object frame = XCAR (frmcons);
2274 if (FRAME_X_SHELL_WIDGET (XFRAME (frame)) == parentwid)
2281 DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
2282 Get the ID of the X11 window.
2283 This gives us a chance to manipulate the Emacs window from within a
2284 different program. Since the ID is an unsigned long, we return it as
2290 struct frame *f = decode_x_frame (frame);
2292 sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
2293 return build_string (str);
2297 /************************************************************************/
2298 /* manipulating the X window */
2299 /************************************************************************/
2302 x_set_frame_position (struct frame *f, int xoff, int yoff)
2304 Widget w = FRAME_X_SHELL_WIDGET (f);
2305 Display *dpy = XtDisplay (w);
2306 Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
2307 Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
2308 Dimension shell_w, shell_h, shell_bord;
2312 XtSetArg (al [0], XtNwidth, &shell_w);
2313 XtSetArg (al [1], XtNheight, &shell_h);
2314 XtSetArg (al [2], XtNborderWidth, &shell_bord);
2315 XtGetValues (w, al, 3);
2318 xoff >= 0 && yoff >= 0 ? NorthWestGravity :
2319 xoff >= 0 ? SouthWestGravity :
2320 yoff >= 0 ? NorthEastGravity :
2323 xoff += frame_w - shell_w - 2*shell_bord;
2325 yoff += frame_h - shell_h - 2*shell_bord;
2327 /* Update the hints so that, if this window is currently iconified, it will
2328 come back at the right place. We can't look at s->visible to determine
2329 whether it is iconified because it might not be up-to-date yet (the queue
2330 might not be processed). */
2331 XtSetArg (al [0], XtNwinGravity, win_gravity);
2332 XtSetArg (al [1], XtNx, xoff);
2333 XtSetArg (al [2], XtNy, yoff);
2334 XtSetValues (w, al, 3);
2336 /* Sometimes you will find that
2338 (set-frame-position (selected-frame) -50 -50)
2340 doesn't put the frame where you expect it to: i.e. it's closer to
2341 the lower-right corner than it should be, and it appears that the
2342 size of the WM decorations was not taken into account. This is
2343 *not* a problem with this function. Both mwm and twm have bugs
2344 in handling this situation. (mwm ignores the window gravity and
2345 always assumes NorthWest, except the first time you map the
2346 window; twm gets things almost right, but forgets to account for
2347 the border width of the top-level window.) This function does
2348 what it's supposed to according to the ICCCM, and I'm not about
2349 to hack around window-manager bugs. */
2352 /* This is not necessary under either mwm or twm */
2353 x_wm_mark_shell_position_user_specified (w);
2357 /* Call this to change the size of frame S's x-window. */
2360 x_set_frame_size (struct frame *f, int cols, int rows)
2362 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
2364 /* this is not correct. x_set_frame_size() is called from
2365 Fset_frame_size(), which may or may not have been called
2366 by the user (e.g. update_EmacsFrame() calls it when the font
2367 changes). For now, don't bother with getting this right. */
2368 x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
2373 x_set_mouse_position (struct window *w, int x, int y)
2375 struct frame *f = XFRAME (w->frame);
2377 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2378 XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
2379 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
2383 x_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
2385 Display *display = DEVICE_X_DISPLAY (d);
2386 Window child_window;
2391 unsigned int keys_and_buttons;
2394 if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
2395 &root_window, &child_window, &root_x, &root_y,
2396 &win_x, &win_y, &keys_and_buttons) == False)
2399 if (child_window == None)
2400 return 0; /* not over any window. */
2405 if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
2406 &win_x, &win_y, &child_window) == False)
2410 if (child_window == None)
2414 /* At this point, win is the innermost window containing the pointer
2415 and win_x and win_y are the coordinates of that window. */
2416 f = x_any_window_to_frame (d, win);
2419 XSETFRAME (*frame, f);
2421 if (XTranslateCoordinates (display, win,
2422 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2423 win_x, win_y, x, y, &child_window) == False)
2431 x_cant_notify_wm_error (void)
2433 error ("Can't notify window manager of iconification.");
2436 /* Raise frame F. */
2438 x_raise_frame_1 (struct frame *f, int force)
2440 if (FRAME_VISIBLE_P (f) || force)
2442 Widget bottom_dialog;
2445 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2446 Window emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
2448 /* first raises all the dialog boxes, then put emacs just below the
2449 * bottom most dialog box */
2450 bottom_dialog = lw_raise_all_pop_up_widgets ();
2451 if (bottom_dialog && XtWindow (bottom_dialog))
2453 xwc.sibling = XtWindow (bottom_dialog);
2454 xwc.stack_mode = Below;
2455 flags = CWSibling | CWStackMode;
2459 xwc.stack_mode = Above;
2460 flags = CWStackMode;
2463 if (!XReconfigureWMWindow (display, emacs_window,
2464 DefaultScreen (display),
2466 x_cant_notify_wm_error ();
2471 x_raise_frame (struct frame *f)
2473 x_raise_frame_1 (f, 1);
2476 /* Lower frame F. */
2478 x_lower_frame (struct frame *f)
2480 if (FRAME_VISIBLE_P (f))
2482 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2484 unsigned int flags = CWStackMode;
2486 xwc.stack_mode = Below;
2487 if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
2488 DefaultScreen (display), flags, &xwc))
2489 x_cant_notify_wm_error ();
2494 x_enable_frame (struct frame *f)
2496 XtSetSensitive (FRAME_X_SHELL_WIDGET (f), True);
2500 x_disable_frame (struct frame *f)
2502 XtSetSensitive (FRAME_X_SHELL_WIDGET (f), False);
2505 /* Change from withdrawn state to mapped state. */
2507 x_make_frame_visible (struct frame *f)
2509 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2511 if (!FRAME_VISIBLE_P(f))
2512 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2514 x_raise_frame_1 (f, 0);
2517 /* Change from mapped state to withdrawn state. */
2519 x_make_frame_invisible (struct frame *f)
2521 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2523 if (!FRAME_VISIBLE_P(f))
2526 if (!XWithdrawWindow (display,
2527 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2528 DefaultScreen (display)))
2529 x_cant_notify_wm_error ();
2533 x_frame_visible_p (struct frame *f)
2536 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2537 XWindowAttributes xwa;
2541 This is bad, very bad :-(
2542 It is not compatible with our tristate visible and
2543 it should never ever change the visibility for us, this leads to
2544 the frame-freeze problem under fvwm because with the pager
2546 Mappedness != Viewability != Visibility != Emacs f->visible
2548 This first unequalness is the reason for the frame freezing problem
2549 under fvwm (it happens when the frame is another fvwm-page)
2551 The second unequalness happen when it is on the same fvwm-page
2552 but in an invisible part of the visible screen.
2554 For now we just return the XEmacs internal value --- which might not be up
2555 to date. Is that a problem? ---. Otherwise we should
2556 use async visibility like in standard Emacs.
2559 if (!XGetWindowAttributes (display,
2560 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2564 result = xwa.map_state == IsViewable;
2565 /* In this implementation it should at least be != IsUnmapped
2568 f->visible = result;
2576 x_frame_totally_visible_p (struct frame *f)
2578 return FRAME_X_TOTALLY_VISIBLE_P (f);
2581 /* Change window state from mapped to iconified. */
2583 x_iconify_frame (struct frame *f)
2585 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2587 if (!XIconifyWindow (display,
2588 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2589 DefaultScreen (display)))
2590 x_cant_notify_wm_error ();
2595 /* Sets the X focus to frame f. */
2597 x_focus_on_frame (struct frame *f)
2599 XWindowAttributes xwa;
2600 Widget shell_widget;
2603 assert (FRAME_X_P (f));
2605 shell_widget = FRAME_X_SHELL_WIDGET (f);
2606 if (!XtWindow (shell_widget))
2609 #ifdef EXTERNAL_WIDGET
2610 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2611 ExternalShellSetFocus (shell_widget);
2612 #endif /* EXTERNAL_WIDGET */
2614 /* Do the ICCCM focus change if the window is still visible.
2615 The s->visible flag might not be up-to-date, because we might
2616 not have processed magic events recently. So make a server
2617 round-trip to find out whether it's really mapped right now.
2618 We grab the server to do this, because that's the only way to
2619 eliminate the race condition.
2621 XGrabServer (XtDisplay (shell_widget));
2622 if (XGetWindowAttributes (XtDisplay (shell_widget),
2623 XtWindow (shell_widget),
2625 /* JV: it is bad to change the visibility like this, so we don't for the
2626 moment, at least change_frame_visibility should be called
2627 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2628 but still X-invisible
2629 f->visible = xwa.map_state == IsViewable; */
2630 viewable = xwa.map_state == IsViewable;
2637 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2638 /* Don't explicitly set the focus on this window unless the focus
2639 was on some other window (not PointerRoot). Note that, even when
2640 running a point-to-type window manager like *twm, there is always
2641 a focus window; the window manager maintains that based on the
2642 mouse position. If you set the "NoTitleFocus" option in these
2643 window managers, then the server itself maintains the focus via
2644 PointerRoot, and changing that to focus on the window would make
2645 the window grab the focus. Very bad.
2647 if (focus != PointerRoot)
2649 XSetInputFocus (XtDisplay (shell_widget),
2650 XtWindow (shell_widget),
2652 DEVICE_X_MOUSE_TIMESTAMP
2653 (XDEVICE (FRAME_DEVICE (f))));
2654 XFlush (XtDisplay (shell_widget));
2657 XUngrabServer (XtDisplay (shell_widget));
2658 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2661 /* Destroy the X window of frame F. */
2663 x_delete_frame (struct frame *f)
2667 #ifndef HAVE_WMCOMMAND
2668 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2669 x_wm_maybe_move_wm_command (f);
2670 #endif /* HAVE_WMCOMMAND */
2673 DtDndDropUnregister (FRAME_X_TEXT_WIDGET (f));
2674 #endif /* HAVE_CDE */
2676 assert (FRAME_X_SHELL_WIDGET (f) != 0);
2677 dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
2679 #ifdef EXTERNAL_WIDGET
2680 expect_x_error (dpy);
2681 /* for obscure reasons having (I think) to do with the internal
2682 window-to-widget hierarchy maintained by Xt, we have to call
2683 XtUnrealizeWidget() here. Xt can really suck. */
2684 if (f->being_deleted)
2685 XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
2686 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2687 x_error_occurred_p (dpy);
2689 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2690 /* make sure the windows are really gone! */
2691 /* #### Is this REALLY necessary? */
2693 #endif /* EXTERNAL_WIDGET */
2695 FRAME_X_SHELL_WIDGET (f) = 0;
2697 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2699 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2700 FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0;
2705 xfree (f->frame_data);
2711 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2717 XSETFRAME(frame, frm);
2719 if (EQ (name, Qforeground))
2721 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2724 if (!EQ (color, Vthe_null_color_instance))
2726 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2727 XtSetArg (al[ac], XtNforeground, (void *) fgc.pixel); ac++;
2730 else if (EQ (name, Qbackground))
2732 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2735 if (!EQ (color, Vthe_null_color_instance))
2737 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2738 XtSetArg (al[ac], XtNbackground, (void *) bgc.pixel); ac++;
2741 /* Really crappy way to force the modeline shadows to be
2742 redrawn. But effective. */
2743 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2744 MARK_FRAME_CHANGED (frm);
2746 else if (EQ (name, Qfont))
2748 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2750 if (!EQ (font, Vthe_null_font_instance))
2752 XtSetArg (al[ac], XtNfont,
2753 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2760 XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
2762 #ifdef HAVE_TOOLBARS
2763 /* Setting the background clears the entire frame area
2764 including the toolbar so we force an immediate redraw of
2766 if (EQ (name, Qbackground))
2767 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2768 #endif /* HAVE_TOOLBARS */
2770 /* Set window manager resize increment hints according to
2771 the new character size */
2772 if (EQ (name, Qfont))
2773 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2777 /************************************************************************/
2778 /* initialization */
2779 /************************************************************************/
2782 syms_of_frame_x (void)
2784 defsymbol (&Qwindow_id, "window-id");
2785 defsymbol (&Qx_resource_name, "x-resource-name");
2787 DEFSUBR (Fx_window_id);
2789 DEFSUBR (Fcde_start_drag_internal);
2791 #ifdef HAVE_OFFIX_DND
2792 DEFSUBR (Foffix_start_drag_internal);
2797 console_type_create_frame_x (void)
2800 CONSOLE_HAS_METHOD (x, init_frame_1);
2801 CONSOLE_HAS_METHOD (x, init_frame_2);
2802 CONSOLE_HAS_METHOD (x, init_frame_3);
2803 CONSOLE_HAS_METHOD (x, mark_frame);
2804 CONSOLE_HAS_METHOD (x, focus_on_frame);
2805 CONSOLE_HAS_METHOD (x, delete_frame);
2806 CONSOLE_HAS_METHOD (x, get_mouse_position);
2807 CONSOLE_HAS_METHOD (x, set_mouse_position);
2808 CONSOLE_HAS_METHOD (x, raise_frame);
2809 CONSOLE_HAS_METHOD (x, lower_frame);
2810 CONSOLE_HAS_METHOD (x, enable_frame);
2811 CONSOLE_HAS_METHOD (x, disable_frame);
2812 CONSOLE_HAS_METHOD (x, make_frame_visible);
2813 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2814 CONSOLE_HAS_METHOD (x, iconify_frame);
2815 CONSOLE_HAS_METHOD (x, set_frame_size);
2816 CONSOLE_HAS_METHOD (x, set_frame_position);
2817 CONSOLE_HAS_METHOD (x, frame_property);
2818 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2819 CONSOLE_HAS_METHOD (x, frame_properties);
2820 CONSOLE_HAS_METHOD (x, set_frame_properties);
2821 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2822 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2823 CONSOLE_HAS_METHOD (x, frame_visible_p);
2824 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2825 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2826 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2827 CONSOLE_HAS_METHOD (x, set_frame_icon);
2828 CONSOLE_HAS_METHOD (x, get_frame_parent);
2829 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2833 vars_of_frame_x (void)
2835 #ifdef EXTERNAL_WIDGET
2836 Fprovide (intern ("external-widget"));
2839 /* this call uses only safe functions from emacs.c */
2840 init_x_prop_symbols ();
2842 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2843 Plist of default frame-creation properties for X frames.
2844 These override what is specified in the resource database and in
2845 `default-frame-plist', but are overridden by the arguments to the
2846 particular call to `make-frame'.
2848 Note: In many cases, properties of a frame are available as specifiers
2849 instead of through the frame-properties mechanism.
2851 Here is a list of recognized frame properties, other than those
2852 documented in `set-frame-properties' (they can be queried and
2853 set at any time, except as otherwise noted):
2855 window-id The X window ID corresponding to the
2856 frame. May be set only at startup, and
2857 only if external widget support was
2858 compiled in; doing so causes the frame
2859 to be created as an "external widget"
2860 in another program that uses an existing
2861 window in the program rather than creating
2863 initially-unmapped If non-nil, the frame will not be visible
2864 when it is created. In this case, you
2865 need to call `make-frame-visible' to make
2867 popup If non-nil, it should be a frame, and this
2868 frame will be created as a "popup" frame
2869 whose parent is the given frame. This
2870 will make the window manager treat the
2871 frame as a dialog box, which may entail
2872 doing different things (e.g. not asking
2873 for positioning, and not iconifying
2874 separate from its parent).
2875 inter-line-space Not currently implemented.
2876 toolbar-shadow-thickness Thickness of toolbar shadows.
2877 background-toolbar-color Color of toolbar background.
2878 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2879 (*Not* specific to the bottom-toolbar.)
2880 top-toolbar-shadow-color Color of top shadows on toolbars.
2881 (*Not* specific to the top-toolbar.)
2882 internal-border-width Width of internal border around text area.
2883 border-width Width of external border around text area.
2884 top Y position (in pixels) of the upper-left
2885 outermost corner of the frame (i.e. the
2886 upper-left of the window-manager
2888 left X position (in pixels) of the upper-left
2889 outermost corner of the frame (i.e. the
2890 upper-left of the window-manager
2892 border-color Color of external border around text area.
2893 cursor-color Color of text cursor.
2895 See also `default-frame-plist', which specifies properties which apply
2896 to all frames, not just X frames.
2898 Vdefault_x_frame_plist = Qnil;
2900 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;