1 /* Functions for the X window system.
2 Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not synched with FSF. */
24 /* Substantially rewritten for XEmacs. */
29 #include "console-x.h"
30 #include "xintrinsicp.h" /* CoreP.h needs this */
31 #include <X11/CoreP.h> /* Numerous places access the fields of
32 a core widget directly. We could
33 use XtGetValues(), but ... */
34 #include <X11/Shell.h>
35 #include <X11/ShellP.h>
37 #include "EmacsManager.h"
38 #include "EmacsFrameP.h"
39 #include "EmacsShell.h"
40 #ifdef EXTERNAL_WIDGET
41 #include "ExternalShell.h"
44 #include "objects-x.h"
45 #include "scrollbar-x.h"
61 #if defined (HAVE_OFFIX_DND) || defined (HAVE_CDE)
62 #include "events-mod.h"
65 /* Default properties to use when creating frames. */
66 Lisp_Object Vdefault_x_frame_plist;
68 Lisp_Object Qwindow_id;
69 Lisp_Object Qx_resource_name;
71 EXFUN (Fx_window_id, 1);
74 /************************************************************************/
75 /* helper functions */
76 /************************************************************************/
78 /* Return the Emacs frame-object corresponding to an X window */
80 x_window_to_frame (struct device *d, Window wdesc)
82 Lisp_Object tail, frame;
85 /* This function was previously written to accept only a window argument
86 (and to loop over all devices looking for a matching window), but
87 that is incorrect because window ID's are not unique across displays. */
89 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
95 if (FRAME_X_P (f) && XtWindow (FRAME_X_TEXT_WIDGET (f)) == wdesc)
101 /* Like x_window_to_frame but also compares the window with the widget's
104 x_any_window_to_frame (struct device *d, Window wdesc)
107 assert (DEVICE_X_P (d));
109 w = XtWindowToWidget (DEVICE_X_DISPLAY (d), wdesc);
114 /* We used to map over all frames here and then map over all widgets
115 belonging to that frame. However it turns out that this was very fragile
116 as it requires our display stuctures to be in sync _and_ that the
117 loop is told about every new widget somebody adds. Therefore we
118 now let Xt find it for us (which does a bottom-up search which
119 could even be faster) */
120 return x_any_widget_or_parent_to_frame (d, w);
123 static struct frame *
124 x_find_frame_for_window (struct device *d, Window wdesc)
126 Lisp_Object tail, frame;
128 /* This function was previously written to accept only a window argument
129 (and to loop over all devices looking for a matching window), but
130 that is incorrect because window ID's are not unique across displays. */
132 for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
136 /* This frame matches if the window is any of its widgets. */
137 if (wdesc == XtWindow (FRAME_X_SHELL_WIDGET (f)) ||
138 wdesc == XtWindow (FRAME_X_CONTAINER_WIDGET (f)) ||
139 wdesc == XtWindow (FRAME_X_TEXT_WIDGET (f)))
142 /* Match if the window is one of the widgets at the top of the frame
143 (menubar, Energize psheets). */
145 /* Note: Jamie once said
147 "Do *not* match if the window is this frame's psheet."
149 But this is wrong and will screw up some functions that expect
150 x_any_window_to_frame() to work as advertised. I think the reason
151 for this statement is that, in the old (broken) event loop, where
152 not all events went through XtDispatchEvent(), psheet events
153 would incorrectly get sucked away by Emacs if this function matched
154 on psheet widgets. */
156 /* Note: that this called only from
157 x_any_widget_or_parent_to_frame it is unnecessary to iterate
158 over the top level widgets. */
160 /* Note: we use to special case scrollbars but this turns out to be a bad idea
162 1. We sometimes get events for _unmapped_ scrollbars and our
163 callers don't want us to fail.
164 2. Starting with the 21.2 widget stuff there are now loads of
165 widgets to check and it is easy to forget adding them in a loop here.
166 See x_any_window_to_frame
167 3. We pick up all widgets now anyway. */
174 x_any_widget_or_parent_to_frame (struct device *d, Widget widget)
178 struct frame *f = x_find_frame_for_window (d, XtWindow (widget));
181 widget = XtParent (widget);
188 decode_x_frame (Lisp_Object frame)
191 XSETFRAME (frame, selected_frame ());
192 CHECK_LIVE_FRAME (frame);
193 /* this will also catch dead frames, but putting in the above check
194 results in a more useful error */
195 CHECK_X_FRAME (frame);
196 return XFRAME (frame);
200 /************************************************************************/
201 /* window-manager interactions */
202 /************************************************************************/
205 /* Not currently used. */
208 x_wm_mark_shell_size_user_specified (Widget wmshell)
210 if (! XtIsWMShell (wmshell)) abort ();
211 EmacsShellSetSizeUserSpecified (wmshell);
215 x_wm_mark_shell_position_user_specified (Widget wmshell)
217 if (! XtIsWMShell (wmshell)) abort ();
218 EmacsShellSetPositionUserSpecified (wmshell);
224 x_wm_set_shell_iconic_p (Widget shell, int iconic_p)
226 if (! XtIsWMShell (shell)) abort ();
228 /* Because of questionable logic in Shell.c, this sequence can't work:
230 w = XtCreatePopupShell (...);
231 Xt_SET_VALUE (w, XtNiconic, True);
234 The iconic resource is only consulted at initialization time (when
235 XtCreatePopupShell is called) instead of at realization time (just
236 before the window gets created, which would be more sensible) or
237 at management-time (just before the window gets mapped, which would
238 be most sensible of all).
240 The bug is that Shell's SetValues method doesn't do anything to
241 w->wm.wm_hints.initial_state until after the widget has been realized.
242 Calls to XtSetValues are ignored in the window between creation and
243 realization. This is true of MIT X11R5 patch level 25, at least.
244 (Apparently some other versions of Xt don't have this bug?)
246 Xt_SET_VALUE (shell, XtNiconic, iconic_p);
247 EmacsShellSmashIconicHint (shell, iconic_p);
251 x_wm_set_cell_size (Widget wmshell, int cw, int ch)
255 if (!XtIsWMShell (wmshell))
257 if (cw <= 0 || ch <= 0)
260 XtSetArg (al [0], XtNwidthInc, cw);
261 XtSetArg (al [1], XtNheightInc, ch);
262 XtSetValues (wmshell, al, 2);
266 x_wm_set_variable_size (Widget wmshell, int width, int height)
270 if (!XtIsWMShell (wmshell))
272 #ifdef DEBUG_GEOMETRY_MANAGEMENT
273 /* See comment in EmacsShell.c */
274 printf ("x_wm_set_variable_size: %d %d\n", width, height);
278 XtSetArg (al [0], XtNwidthCells, width);
279 XtSetArg (al [1], XtNheightCells, height);
280 XtSetValues (wmshell, al, 2);
283 /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS
284 and WM_DELETE_WINDOW, then add them. (They may already be present
285 because of the toolkit (Motif adds them, for example, but Xt doesn't).
288 x_wm_hack_wm_protocols (Widget widget)
290 Display *dpy = XtDisplay (widget);
291 struct device *d = get_device_from_display (dpy);
292 Window w = XtWindow (widget);
296 assert (XtIsWMShell (widget));
299 Atom type, *atoms = 0;
301 unsigned long nitems = 0;
302 unsigned long bytes_after;
304 if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d),
305 0, 100, False, XA_ATOM,
306 &type, &format, &nitems, &bytes_after,
307 (unsigned char **) &atoms)
308 && format == 32 && type == XA_ATOM)
312 if (atoms [nitems] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
314 else if (atoms [nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
317 if (atoms) XFree ((char *) atoms);
322 if (need_delete) props[count++] = DEVICE_XATOM_WM_DELETE_WINDOW (d);
323 if (need_focus) props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d);
325 XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32,
326 PropModeAppend, (unsigned char *) props, count);
331 x_wm_store_class_hints (Widget shell, char *frame_name)
333 Display *dpy = XtDisplay (shell);
334 char *app_name, *app_class;
335 XClassHint classhint;
337 if (!XtIsWMShell (shell))
340 XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
341 classhint.res_name = frame_name;
342 classhint.res_class = app_class;
343 XSetClassHint (dpy, XtWindow (shell), &classhint);
346 #ifndef HAVE_WMCOMMAND
348 x_wm_maybe_store_wm_command (struct frame *f)
350 Widget w = FRAME_X_SHELL_WIDGET (f);
351 struct device *d = XDEVICE (FRAME_DEVICE (f));
353 if (!XtIsWMShell (w))
356 if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
360 make_argc_argv (Vcommand_line_args, &argc, &argv);
361 XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
362 free_argc_argv (argv);
363 XSETFRAME (DEVICE_X_WM_COMMAND_FRAME (d), f);
367 /* If we're deleting the frame on which the WM_COMMAND property has been
368 set, then move that property to another frame so that there is exactly
369 one frame that has that property set.
372 x_wm_maybe_move_wm_command (struct frame *f)
374 struct device *d = XDEVICE (FRAME_DEVICE (f));
376 /* There may not be a frame in DEVICE_X_WM_COMMAND_FRAME()
377 if we C-c'ed at startup at the right time. */
378 if (FRAMEP (DEVICE_X_WM_COMMAND_FRAME (d))
379 && f == XFRAME (DEVICE_X_WM_COMMAND_FRAME (d)))
381 Lisp_Object rest = DEVICE_FRAME_LIST (d);
382 DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
383 /* find some random other X frame that is not this one, or give up */
384 /* skip non-top-level (ExternalClient) frames */
385 while (!NILP (rest) &&
386 (f == XFRAME (XCAR (rest)) ||
387 !FRAME_X_TOP_LEVEL_FRAME_P (XFRAME (XCAR (rest)))))
391 f = XFRAME (XCAR (rest));
393 x_wm_maybe_store_wm_command (f);
397 #endif /* !HAVE_WMCOMMAND */
400 x_frame_iconified_p (struct frame *f)
404 unsigned long nitems, bytesafter;
405 unsigned long *datap = 0;
408 struct device *d = XDEVICE (FRAME_DEVICE (f));
410 widget = FRAME_X_SHELL_WIDGET (f);
411 if (Success == XGetWindowProperty (XtDisplay (widget), XtWindow (widget),
412 DEVICE_XATOM_WM_STATE (d), 0, 2, False,
413 DEVICE_XATOM_WM_STATE (d), &actual_type,
414 &actual_format, &nitems, &bytesafter,
415 (unsigned char **) &datap)
418 if (nitems <= 2 /* "suggested" by ICCCM version 1 */
419 && datap[0] == IconicState)
421 XFree ((char *) datap);
427 /************************************************************************/
428 /* frame properties */
429 /************************************************************************/
431 /* Connect the frame-property names (symbols) to the corresponding
432 X Resource Manager names. The name of a property, as a Lisp symbol,
433 has an `x-resource-name' property which is a Lisp_String. */
436 init_x_prop_symbols (void)
438 #define def(sym, rsrc) \
439 Fput (sym, Qx_resource_name, build_string (rsrc))
440 #define defi(sym,rsrc) \
441 def (sym, rsrc); Fput (sym, Qintegerp, Qt)
443 #if 0 /* this interferes with things. #### fix this right */
444 def (Qminibuffer, XtNminibuffer);
445 def (Qunsplittable, XtNunsplittable);
447 defi(Qinternal_border_width, XtNinternalBorderWidth);
449 def (Qtop_toolbar_shadow_color, XtNtopToolBarShadowColor);
450 def (Qbottom_toolbar_shadow_color, XtNbottomToolBarShadowColor);
451 def (Qbackground_toolbar_color, XtNbackgroundToolBarColor);
452 def (Qtop_toolbar_shadow_pixmap, XtNtopToolBarShadowPixmap);
453 def (Qbottom_toolbar_shadow_pixmap, XtNbottomToolBarShadowPixmap);
454 defi(Qtoolbar_shadow_thickness, XtNtoolBarShadowThickness);
456 def (Qscrollbar_placement, XtNscrollBarPlacement);
457 defi(Qinter_line_space, XtNinterline);
458 /* font, foreground */
459 def (Qiconic, XtNiconic);
460 def (Qbar_cursor, XtNbarCursor);
461 def (Qvisual_bell, XtNvisualBell);
462 defi(Qbell_volume, XtNbellVolume);
463 def (Qpointer_background, XtNpointerBackground);
464 def (Qpointer_color, XtNpointerColor);
465 def (Qtext_pointer, XtNtextPointer);
466 def (Qspace_pointer, XtNspacePointer);
467 def (Qmodeline_pointer, XtNmodeLinePointer);
468 def (Qgc_pointer, XtNgcPointer);
469 /* geometry, initial_geometry */
470 def (Qinitially_unmapped, XtNinitiallyUnmapped);
471 /* preferred_width, preferred_height */
472 def (Quse_backing_store, XtNuseBackingStore);
476 def (Qborder_color, XtNborderColor);
477 defi(Qborder_width, XtNborderWidth);
478 defi(Qwidth, XtNwidth);
479 defi(Qheight, XtNheight);
487 color_to_string (Widget w, unsigned long pixel)
493 XQueryColor (XtDisplay (w), w->core.colormap, &color);
494 sprintf (buf, "#%04x%04x%04x", color.red, color.green, color.blue);
495 return build_string (buf);
499 x_get_top_level_position (Display *d, Window w, Position *x, Position *y)
501 Window root, parent = w, *children;
502 unsigned int nchildren;
503 XWindowAttributes xwa;
508 if (!XQueryTree (d, w, &root, &parent, &children, &nchildren))
516 while (root != parent);
517 XGetWindowAttributes (d, w, &xwa);
524 x_smash_bastardly_shell_position (Widget shell)
526 /* Naturally those bastards who wrote Xt couldn't be bothered
527 to learn about race conditions and such. We can't trust
528 the X and Y values to have any semblance of correctness,
529 so we smash the right values in place. */
531 /* We might be called before we've actually realized the window (if
532 we're checking for the minibuffer resource). This will bomb in
533 that case so we don't bother calling it. */
534 if (XtWindow (shell))
535 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
536 &shell->core.x, &shell->core.y);
541 x_frame_property (struct frame *f, Lisp_Object property)
543 Widget shell = FRAME_X_SHELL_WIDGET (f);
544 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
545 Widget gw = (Widget) w;
547 if (EQ (Qleft, property) || EQ (Qtop, property))
550 if (!XtWindow(shell))
552 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
553 if (EQ (Qleft, property)) return make_int (x);
554 if (EQ (Qtop, property)) return make_int (y);
556 if (EQ (Qborder_width, property))
557 return make_int (w->core.border_width);
558 if (EQ (Qinternal_border_width, property))
559 return make_int (w->emacs_frame.internal_border_width);
560 if (EQ (Qborder_color, property))
561 return color_to_string (gw, w->core.border_pixel);
563 if (EQ (Qtop_toolbar_shadow_color, property))
564 return color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel);
565 if (EQ (Qbottom_toolbar_shadow_color, property))
566 return color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel);
567 if (EQ (Qbackground_toolbar_color, property))
568 return color_to_string (gw, w->emacs_frame.background_toolbar_pixel);
569 if (EQ (Qtoolbar_shadow_thickness, property))
570 return make_int (w->emacs_frame.toolbar_shadow_thickness);
571 #endif /* HAVE_TOOLBARS */
572 if (EQ (Qinter_line_space, property))
573 return make_int (w->emacs_frame.interline);
574 if (EQ (Qwindow_id, property))
575 return Fx_window_id (make_frame (f));
581 x_internal_frame_property_p (struct frame *f, Lisp_Object property)
583 return EQ (property, Qleft)
584 || EQ (property, Qtop)
585 || EQ (property, Qborder_width)
586 || EQ (property, Qinternal_border_width)
587 || EQ (property, Qborder_color)
589 || EQ (property, Qtop_toolbar_shadow_color)
590 || EQ (property, Qbottom_toolbar_shadow_color)
591 || EQ (property, Qbackground_toolbar_color)
592 || EQ (property, Qtoolbar_shadow_thickness)
593 #endif /* HAVE_TOOLBARS */
594 || EQ (property, Qinter_line_space)
595 || EQ (property, Qwindow_id)
596 || STRINGP (property);
600 x_frame_properties (struct frame *f)
602 Lisp_Object props = Qnil;
603 Widget shell = FRAME_X_SHELL_WIDGET (f);
604 EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
605 Widget gw = (Widget) w;
608 props = cons3 (Qwindow_id, Fx_window_id (make_frame (f)), props);
609 props = cons3 (Qinter_line_space, make_int (w->emacs_frame.interline), props);
612 props = cons3 (Qtoolbar_shadow_thickness,
613 make_int (w->emacs_frame.toolbar_shadow_thickness),
615 props = cons3 (Qbackground_toolbar_color,
616 color_to_string (gw, w->emacs_frame.background_toolbar_pixel),
618 props = cons3 (Qbottom_toolbar_shadow_color,
619 color_to_string (gw, w->emacs_frame.bottom_toolbar_shadow_pixel),
621 props = cons3 (Qtop_toolbar_shadow_color,
622 color_to_string (gw, w->emacs_frame.top_toolbar_shadow_pixel),
624 #endif /* HAVE_TOOLBARS */
626 props = cons3 (Qborder_color,
627 color_to_string (gw, w->core.border_pixel), props);
628 props = cons3 (Qinternal_border_width,
629 make_int (w->emacs_frame.internal_border_width), props);
630 props = cons3 (Qborder_width, make_int (w->core.border_width), props);
632 if (!XtWindow(shell))
635 x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
637 props = cons3 (Qtop, make_int (y), props);
638 props = cons3 (Qleft, make_int (x), props);
644 /* Functions called only from `x_set_frame_properties' to set
645 individual properties. */
648 x_set_frame_text_value (struct frame *f, Bufbyte *value,
649 String Xt_resource_name,
650 String Xt_resource_encoding_name)
652 Atom encoding = XA_STRING;
653 String new_XtValue = (String) value;
654 String old_XtValue = NULL;
658 /* Optimize for common ASCII case */
659 for (ptr = value; *ptr; ptr++)
660 if (!BYTE_ASCII_P (*ptr))
663 encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f)));
664 TO_EXTERNAL_FORMAT (C_STRING, value,
665 C_STRING_ALLOCA, tmp,
667 new_XtValue = (String) tmp;
672 /* #### Caching is device-independent - belongs in update_frame_title. */
673 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
674 if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
677 XtSetArg (al[0], Xt_resource_name, new_XtValue);
678 XtSetArg (al[1], Xt_resource_encoding_name, encoding);
679 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
684 x_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
686 x_set_frame_text_value (f, name, XtNtitle, XtNtitleEncoding);
690 x_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
692 x_set_frame_text_value (f, name, XtNiconName, XtNiconNameEncoding);
695 /* Set the initial frame size as specified. This function is used
696 when the frame's widgets have not yet been realized. In this
697 case, it is not sufficient just to set the width and height of
698 the EmacsFrame widget, because they will be ignored when the
699 widget is realized (instead, the shell's geometry resource is
703 x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
704 unsigned int w, unsigned int h)
706 char shell_geom [255];
709 char uspos = !!(flags & (XValue | YValue));
710 char ussize = !!(flags & (WidthValue | HeightValue));
713 /* assign the correct size to the EmacsFrame widget ... */
714 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
716 /* and also set the WMShell's geometry */
717 (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
718 (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
721 sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
723 sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
725 sprintf (shell_geom, "=%dx%d", w, h);
729 temp = (char *) xmalloc (1 + strlen (shell_geom));
730 strcpy (temp, shell_geom);
731 FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
736 Xt_SET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp);
739 /* Report to X that a frame property of frame S is being set or changed.
740 If the property is not specially recognized, do nothing.
744 x_set_frame_properties (struct frame *f, Lisp_Object plist)
747 Dimension width = 0, height = 0;
748 Bool width_specified_p = False;
749 Bool height_specified_p = False;
750 Bool x_position_specified_p = False;
751 Bool y_position_specified_p = False;
752 Bool internal_border_width_specified = False;
754 Widget w = FRAME_X_TEXT_WIDGET (f);
756 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
758 Lisp_Object prop = Fcar (tail);
759 Lisp_Object val = Fcar (Fcdr (tail));
765 if (XSTRING_LENGTH (prop) == 0)
768 TO_EXTERNAL_FORMAT (LISP_STRING, prop,
769 C_STRING_ALLOCA, extprop,
773 const Extbyte *extval;
776 TO_EXTERNAL_FORMAT (LISP_STRING, val,
777 ALLOCA, (extval, extvallen),
779 XtVaSetValues (w, XtVaTypedArg, extprop,
780 XtRString, extval, extvallen + 1,
784 XtVaSetValues (w, XtVaTypedArg, extprop, XtRInt,
785 XINT (val), sizeof (int),
788 else if (SYMBOLP (prop))
790 Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
791 int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
793 if (NILP (prop) || NILP (str))
795 /* Kludge to handle the font property. */
796 if (EQ (prop, Qfont))
798 /* If the value is not a string we silently ignore it. */
801 Lisp_Object frm, font_spec;
804 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
806 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
807 update_frame_face_values (f);
817 /* Kludge the width/height so that we interpret them in characters
818 instead of pixels. Yuck yuck yuck. */
819 if (!strcmp ((char *) XSTRING_DATA (str), "width"))
823 width_specified_p = True;
826 if (!strcmp ((char *) XSTRING_DATA (str), "height"))
830 height_specified_p = True;
833 /* Further kludge the x/y. */
834 if (!strcmp ((char *) XSTRING_DATA (str), "x"))
837 x = (Position) XINT (val);
838 x_position_specified_p = True;
841 if (!strcmp ((char *) XSTRING_DATA (str), "y"))
844 y = (Position) XINT (val);
845 y_position_specified_p = True;
848 /* Have you figured out by now that this entire function is
849 one gigantic kludge? */
850 if (!strcmp ((char *) XSTRING_DATA (str),
851 "internalBorderWidth"))
853 internal_border_width_specified = True;
859 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val));
861 else if (EQ (val, Qt))
863 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/
865 else if (EQ (val, Qnil))
867 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/
872 XtVaSetValues (w, XtVaTypedArg,
874 (char *) XSTRING_DATA (str),
877 XSTRING_LENGTH (val) + 1,
881 #ifdef HAVE_SCROLLBARS
882 if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth")
883 || !strcmp ((char *) XSTRING_DATA (str),
886 x_update_frame_scrollbars (f);
888 #endif /* HAVE_SCROLLBARS */
892 /* Kludge kludge kludge. We need to deal with the size and position
895 int size_specified_p = width_specified_p || height_specified_p;
896 int position_specified_p = x_position_specified_p ||
897 y_position_specified_p;
899 if (!width_specified_p)
900 width = FRAME_WIDTH (f);
901 if (!height_specified_p)
902 height = FRAME_HEIGHT (f);
904 /* Kludge kludge kludge kludge. */
905 if (position_specified_p &&
906 (!x_position_specified_p || !y_position_specified_p))
909 Widget shell = FRAME_X_SHELL_WIDGET (f);
910 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
911 (x_position_specified_p ? &dummy : &x),
912 (y_position_specified_p ? &dummy : &y));
914 x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
915 y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
919 if (!f->init_finished)
921 int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
922 (position_specified_p ?
923 XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
926 || position_specified_p
927 || internal_border_width_specified)
928 x_set_initial_frame_size (f, flags, x, y, width, height);
932 if (size_specified_p || internal_border_width_specified)
935 XSETFRAME (frame, f);
936 Fset_frame_size (frame, make_int (width),
937 make_int (height), Qnil);
939 if (position_specified_p)
942 XSETFRAME (frame, f);
943 Fset_frame_position (frame, make_int (x), make_int (y));
949 static int frame_title_format_already_set;
952 maybe_set_frame_title_format (Widget shell)
955 /* Only do this if this is the first X frame we're creating.
957 If the *title resource (or -title option) was specified, then
958 set frame-title-format to its value.
961 if (!frame_title_format_already_set)
963 /* No doubt there's a less stupid way to do this. */
965 XtResource resources [2];
966 results [0] = results [1] = 0;
967 resources [0].resource_name = XtNtitle;
968 resources [0].resource_class = XtCTitle;
969 resources [0].resource_type = XtRString;
970 resources [0].resource_size = sizeof (String);
971 resources [0].resource_offset = 0;
972 resources [0].default_type = XtRString;
973 resources [0].default_addr = 0;
974 resources [1].resource_name = XtNiconName;
975 resources [1].resource_class = XtCIconName;
976 resources [1].resource_type = XtRString;
977 resources [1].resource_size = sizeof (String);
978 resources [1].resource_offset = sizeof (char *);
979 resources [1].default_type = XtRString;
980 resources [1].default_addr = 0;
981 XtGetSubresources (XtParent (shell), (XtPointer) results,
983 shell->core.widget_class->core_class.class_name,
984 resources, XtNumber (resources), 0, 0);
986 Vframe_title_format = build_string (results[0]);
988 Vframe_icon_title_format = build_string (results[1]);
991 frame_title_format_already_set = 1;
998 static Widget CurrentDragWidget = NULL;
999 static XtCallbackRec dnd_convert_cb_rec[2];
1000 static XtCallbackRec dnd_destroy_cb_rec[2];
1001 static int drag_not_done = 0;
1004 x_cde_destroy_callback (Widget widget, XtPointer clientData,
1007 DtDndDragFinishCallbackStruct *dragFinishInfo =
1008 (DtDndDragFinishCallbackStruct *)callData;
1009 DtDndContext *dragData = dragFinishInfo->dragData;
1012 /* free the items */
1013 if (callData != NULL && dragData != NULL)
1015 if (dragData->protocol == DtDND_BUFFER_TRANSFER)
1017 for (i = 0; i < dragData->numItems; i++)
1019 XtFree((char *) dragData->data.buffers[i].bp);
1020 if (dragData->data.buffers[i].name)
1021 XtFree(dragData->data.buffers[i].name);
1026 for (i = 0; i < dragData->numItems; i++)
1027 XtFree(dragData->data.files[i]);
1031 /* free the data string */
1034 CurrentDragWidget = NULL;
1038 x_cde_convert_callback (Widget widget, XtPointer clientData,
1041 DtDndConvertCallbackStruct *convertInfo =
1042 (DtDndConvertCallbackStruct *) callData;
1043 char *textdata = (char *) clientData;
1044 char *textptr = NULL;
1047 if (convertInfo == NULL)
1052 if ((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER
1053 && convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER) ||
1054 (convertInfo->reason != DtCR_DND_CONVERT_DATA))
1059 for (textptr=textdata, i=0;
1060 i<convertInfo->dragData->numItems;
1061 textptr+=strlen(textptr)+1, i++)
1063 if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER)
1065 convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr);
1066 convertInfo->dragData->data.buffers[i].size = strlen(textptr);
1067 convertInfo->dragData->data.buffers[i].name = NULL;
1071 convertInfo->dragData->data.files[i] = XtNewString(textptr);
1075 convertInfo->status = DtDND_SUCCESS;
1079 abort_current_drag(Lisp_Object arg)
1081 if (CurrentDragWidget && drag_not_done)
1083 XmDragCancel(CurrentDragWidget);
1084 CurrentDragWidget = NULL;
1089 DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 3, 3, 0, /*
1090 Start a CDE drag from a buffer.
1091 First argument is the event that started the drag (must be a
1092 button-press-event),
1093 second arg defines if the data should be treated as a buffer or
1094 a filename transfer (set to nil for buffer transfer),
1095 and the third argument is a list of data strings.
1096 WARNING: can only handle plain/text and file: transfers!
1098 (event, dragtype, dragdata))
1102 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1104 Widget wid = FRAME_X_TEXT_WIDGET (f);
1105 Display *display = XtDisplayOfObject (wid);
1106 struct device *d = get_device_from_display (display);
1107 struct x_device *xd = DEVICE_X_DATA (d);
1108 XWindowAttributes win_attrib;
1109 unsigned int modifier = 0, state = 0;
1111 int numItems = 0, textlen = 0, pos = 0;
1112 Lisp_Event *lisp_event = XEVENT (event);
1113 Lisp_Object item = Qnil;
1114 struct gcpro gcpro1;
1116 /* only drag if this is really a press */
1117 if (EVENT_TYPE(lisp_event) != button_press_event
1118 || !LISTP(dragdata))
1124 * not so cross hack that converts a emacs event back to a XEvent
1127 x_event.xbutton.type = ButtonPress;
1128 x_event.xbutton.send_event = False;
1129 x_event.xbutton.display = XtDisplayOfObject(wid);
1130 x_event.xbutton.window = XtWindowOfObject(wid);
1131 x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0);
1132 x_event.xbutton.subwindow = 0;
1133 x_event.xbutton.time = lisp_event->timestamp;
1134 x_event.xbutton.x = lisp_event->event.button.x;
1135 x_event.xbutton.y = lisp_event->event.button.y;
1136 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1137 x_event.xbutton.window,
1140 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1141 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1145 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1146 x_event.xbutton.y_root = lisp_event->event.button.y;
1148 modifier = lisp_event->event.button.modifiers;
1149 if (modifier & MOD_SHIFT) state |= ShiftMask;
1150 if (modifier & MOD_CONTROL) state |= ControlMask;
1151 if (modifier & MOD_META) state |= xd->MetaMask;
1152 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1153 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1154 if (modifier & MOD_ALT) state |= xd->AltMask;
1155 state |= Button1Mask << (lisp_event->event.button.button-1);
1157 x_event.xbutton.state = state;
1158 x_event.xbutton.button = lisp_event->event.button.button;
1159 x_event.xkey.same_screen = True;
1161 /* convert data strings into a big string */
1163 while (!NILP (item))
1165 if (!STRINGP (XCAR (item)))
1170 textlen += XSTRING_LENGTH (XCAR (item)) + 1;
1178 * concatenate all strings given to one large string, with
1179 * \0 as separator. List is ended by \0.
1181 Ctext = (char *)xmalloc (textlen+1);
1185 while (!NILP (item))
1187 if (!STRINGP (XCAR (item)))
1194 strcpy (Ctext+pos, (const char *)XSTRING_DATA (XCAR (item)));
1195 pos += XSTRING_LENGTH (XCAR (item)) + 1;
1200 dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
1201 dnd_convert_cb_rec[0].closure = (XtPointer) Ctext;
1202 dnd_convert_cb_rec[1].callback = NULL;
1203 dnd_convert_cb_rec[1].closure = NULL;
1205 dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
1206 dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext;
1207 dnd_destroy_cb_rec[1].callback = NULL;
1208 dnd_destroy_cb_rec[1].closure = NULL;
1211 DtDndDragStart (wid, &x_event,
1212 (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER),
1222 return numItems?Qt:Qnil;
1229 x_cde_transfer_callback (Widget widget, XtPointer clientData,
1232 char *filePath, *hurl;
1234 Lisp_Object frame = Qnil;
1235 Lisp_Object l_type = Qnil;
1236 Lisp_Object l_data = Qnil;
1237 DtDndTransferCallbackStruct *transferInfo = NULL;
1238 struct gcpro gcpro1, gcpro2, gcpro3;
1241 this needs to be changed to the new protocol:
1242 - we need the button, modifier and pointer states to create a
1243 correct misc_user_event
1244 - the data must be converted to the new format (URL/MIME)
1248 transferInfo = (DtDndTransferCallbackStruct *) callData;
1249 if (transferInfo == NULL)
1252 GCPRO3 (frame, l_type, l_data);
1254 frame = make_frame ((struct frame *) clientData);
1256 if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
1258 l_type = Qdragdrop_URL;
1260 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1262 filePath = transferInfo->dropData->data.files[ii];
1263 hurl = dnd_url_hexify_string ((char *)filePath, "file:");
1264 /* #### Mule-izing required */
1265 l_data = Fcons (make_string ((Bufbyte* )hurl,
1271 else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
1273 int speccount = specpdl_depth();
1275 /* Problem: all buffers a treated as text/plain!!!
1276 Solution: Also support DtDND_TEXT_TRANSFER
1277 perhaps implementation of the Motif protocol
1278 (which is the base of CDE) will clear this */
1279 l_type = Qdragdrop_MIME;
1280 record_unwind_protect(abort_current_drag, Qnil);
1282 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1284 /* let us forget this name thing for now... */
1285 /* filePath = transferInfo->dropData->data.buffers[ii].name;
1286 path = (filePath == NULL) ? Qnil
1287 : make_string ((Bufbyte *)filePath, strlen (filePath)); */
1288 /* what, if the data is no text, and how can I tell it? */
1289 l_data = Fcons ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1290 make_string ((Bufbyte *)"8bit", 4),
1291 make_string ((Bufbyte *)transferInfo->dropData->data.buffers[ii].bp,
1292 transferInfo->dropData->data.buffers[ii].size) ),
1296 unbind_to(speccount, Qnil);
1298 else /* the other cases: NOOP_TRANSFER */
1301 /* The Problem: no button and mods from CDE... */
1303 enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch,
1304 Fcons (l_type, l_data),
1305 0 /* this is the button */,
1306 0 /* these are the mods */,
1313 #endif /* HAVE_CDE */
1315 #ifdef HAVE_OFFIX_DND
1317 DEFUN ("offix-start-drag-internal", Foffix_start_drag_internal, 2, 3, 0, /*
1318 Start a OffiX drag from a buffer.
1319 First arg is the event that started the drag,
1320 second arg should be some string, and the third
1321 is the type of the data (this should be an int).
1322 The type defaults to DndText (4).
1324 (event, data, dtyp))
1328 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1330 Widget wid = FRAME_X_TEXT_WIDGET (f);
1331 Display *display = XtDisplayOfObject (wid);
1332 struct device *d = get_device_from_display (display);
1333 struct x_device *xd = DEVICE_X_DATA (d);
1334 XWindowAttributes win_attrib;
1335 unsigned int modifier = 0, state = 0;
1336 char *dnd_data = NULL;
1337 unsigned long dnd_len = 0;
1338 int dnd_typ = DndText, dnd_dealloc = 0;
1339 Lisp_Event *lisp_event = XEVENT (event);
1341 /* only drag if this is really a press */
1342 if (EVENT_TYPE(lisp_event) != button_press_event)
1345 /* get the desired type */
1346 if (!NILP (dtyp) && INTP (dtyp))
1347 dnd_typ = XINT (dtyp);
1349 if (dnd_typ == DndFiles)
1351 Lisp_Object run = data;
1354 if (NILP ( Flistp (data)))
1357 /* construct the data from a list of files */
1359 dnd_data = (char *) xmalloc (1);
1363 if (!STRINGP (XCAR (run)))
1368 len = XSTRING_LENGTH (XCAR (run)) + 1;
1369 dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
1370 strcpy (dnd_data + dnd_len - 1, (const char *)XSTRING_DATA (XCAR (run)));
1375 dnd_data[dnd_len - 1] = 0; /* the list-ending zero */
1381 if (!STRINGP (data))
1384 /* and what's with MULE data ??? */
1385 dnd_data = (char *)XSTRING_DATA (data);
1386 dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */
1390 /* not so gross hack that converts an emacs event back to a XEvent */
1392 x_event.xbutton.type = ButtonPress;
1393 x_event.xbutton.send_event = False;
1394 x_event.xbutton.display = XtDisplayOfObject(wid);
1395 x_event.xbutton.window = XtWindowOfObject(wid);
1396 x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0);
1397 x_event.xbutton.subwindow = 0;
1398 x_event.xbutton.time = lisp_event->timestamp;
1399 x_event.xbutton.x = lisp_event->event.button.x;
1400 x_event.xbutton.y = lisp_event->event.button.y;
1401 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1402 x_event.xbutton.window,
1405 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1406 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1410 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1411 x_event.xbutton.y_root = lisp_event->event.button.y;
1414 modifier = lisp_event->event.button.modifiers;
1415 if (modifier & MOD_SHIFT) state |= ShiftMask;
1416 if (modifier & MOD_CONTROL) state |= ControlMask;
1417 if (modifier & MOD_META) state |= xd->MetaMask;
1418 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1419 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1420 if (modifier & MOD_ALT) state |= xd->AltMask;
1421 state |= Button1Mask << (lisp_event->event.button.button-1);
1423 x_event.xbutton.state = state;
1424 x_event.xbutton.button = lisp_event->event.button.button;
1425 x_event.xkey.same_screen = True;
1427 DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len);
1431 /* the next thing blocks everything... */
1432 if (DndHandleDragging(wid, &x_event))
1438 #endif /* HAVE_OFFIX_DND */
1441 /************************************************************************/
1442 /* widget creation */
1443 /************************************************************************/
1445 /* The widget hierarchy is
1447 argv[0] shell container FRAME-NAME
1448 ApplicationShell EmacsShell EmacsManager EmacsFrame
1450 We accept geometry specs in this order:
1452 *FRAME-NAME.geometry
1453 *EmacsFrame.geometry
1456 Other possibilities for widget hierarchies might be
1458 argv[0] frame container FRAME-NAME
1459 ApplicationShell EmacsShell EmacsManager EmacsFrame
1461 argv[0] FRAME-NAME container FRAME-NAME
1462 ApplicationShell EmacsShell EmacsManager EmacsFrame
1464 argv[0] FRAME-NAME container emacsTextPane
1465 ApplicationShell EmacsShell EmacsManager EmacsFrame
1467 #ifdef EXTERNAL_WIDGET
1468 The ExternalShell widget is simply a replacement for the Shell widget
1469 which is able to deal with using an externally-supplied window instead
1470 of always creating its own.
1475 #ifdef EXTERNAL_WIDGET
1478 is_valid_window (Window w, struct device *d)
1480 XWindowAttributes xwa;
1481 Display *dpy = DEVICE_X_DISPLAY (d);
1483 expect_x_error (dpy);
1484 XGetWindowAttributes (dpy, w, &xwa);
1485 return !x_error_occurred_p (dpy);
1488 #endif /* EXTERNAL_WIDGET */
1490 /* This sends a synthetic mouse-motion event to the frame, if the mouse
1491 is over the frame. This ensures that the cursor gets set properly
1492 before the user moves the mouse for the first time. */
1495 x_send_synthetic_mouse_event (struct frame *f)
1497 /* #### write this function. */
1501 first_x_frame_p (struct frame *f)
1503 Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
1504 while (!NILP (rest) &&
1505 (f == XFRAME (XCAR (rest)) ||
1506 !FRAME_X_P (XFRAME (XCAR (rest)))))
1511 /* Figure out what size the EmacsFrame widget should initially be,
1512 and set it. Should be called after the default font has been
1513 determined but before the widget has been realized. */
1516 x_initialize_frame_size (struct frame *f)
1518 /* Geometry of the AppShell */
1522 unsigned int app_w = 0;
1523 unsigned int app_h = 0;
1525 /* Geometry of the EmacsFrame */
1526 int frame_flags = 0;
1529 unsigned int frame_w = 0;
1530 unsigned int frame_h = 0;
1532 /* Hairily merged geometry */
1535 unsigned int w = 80;
1536 unsigned int h = 40;
1539 char *geom = 0, *ew_geom = 0;
1540 Boolean iconic_p = False, ew_iconic_p = False;
1542 Widget wmshell = FRAME_X_SHELL_WIDGET (f);
1543 /* #### This may not be an ApplicationShell any more, with the 'popup
1545 Widget app_shell = XtParent (wmshell);
1546 Widget ew = FRAME_X_TEXT_WIDGET (f);
1548 /* set the position of the frame's root window now. When the
1549 frame was created, the position was initialized to (0,0). */
1551 struct window *win = XWINDOW (f->root_window);
1553 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1554 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
1556 if (!NILP (f->minibuffer_window))
1558 win = XWINDOW (f->minibuffer_window);
1559 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1563 #ifdef EXTERNAL_WIDGET
1564 /* If we're an external widget, then the size of the frame is predetermined
1565 (by the client) and is not our decision to make. */
1566 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1571 /* #### this junk has not been tested; therefore it's
1572 probably wrong. Doesn't really matter at this point because
1573 currently all frames are either top-level or external widgets. */
1575 /* If we're not our own top-level window, then we shouldn't go messing around
1576 with top-level shells or "Emacs.geometry" or any such stuff. Therefore,
1577 we do as follows to determine the size of the frame:
1579 1) If a value for the frame's "geometry" resource was specified, then
1580 use it. (This specifies a size in characters.)
1581 2) Else, if the "width" and "height" resources were specified, then
1582 leave them alone. (This is a value in pixels. Sorry, we can't break
1583 Xt conventions here.)
1584 3) Else, assume a size of 64x12. (This is somewhat arbitrary, but
1585 it's unlikely that a size of 80x40 is desirable because we're probably
1586 inside of a dialog box.)
1588 Set the widget's x, y, height, and width as determined. Don't set the
1589 top-level container widget, because we don't necessarily know what it
1590 is. (Assume it is smart and pays attention to our values.)
1593 if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
1595 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1597 frame_flags = XParseGeometry (ew_geom,
1599 &frame_w, &frame_h);
1600 if (! (frame_flags & (WidthValue | HeightValue)))
1603 XtSetArg (al [0], XtNwidth, &frame_w);
1604 XtSetArg (al [1], XtNheight, &frame_h);
1605 XtGetValues (ew, al, 2);
1606 if (!frame_w && !frame_h)
1610 frame_flags |= WidthValue | HeightValue;
1613 if (frame_flags & (WidthValue | HeightValue))
1614 EmacsFrameSetCharSize (ew, frame_w, frame_h);
1615 if (frame_flags & (XValue | YValue))
1618 XtSetArg (al [0], XtNwidth, &frame_w);
1619 XtSetArg (al [1], XtNheight, &frame_h);
1620 XtGetValues (ew, al, 2);
1622 if (frame_flags & XNegative)
1624 if (frame_flags & YNegative)
1627 XtSetArg (al [0], XtNx, frame_x);
1628 XtSetArg (al [1], XtNy, frame_y);
1629 XtSetValues (ew, al, 2);
1635 /* OK, we're a top-level shell. */
1637 if (!XtIsWMShell (wmshell))
1640 /* If the EmacsFrame doesn't have a geometry but the shell does,
1641 treat that as the geometry of the frame.
1642 (Is this bogus? I'm not sure.) */
1644 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1647 Xt_GET_VALUE (wmshell, XtNgeometry, &geom);
1651 Xt_SET_VALUE (ew, XtNgeometry, ew_geom);
1655 /* If the Shell is iconic, then the EmacsFrame is iconic.
1656 (Is this bogus? I'm not sure.) */
1657 Xt_GET_VALUE (ew, XtNiconic, &ew_iconic_p);
1660 Xt_GET_VALUE (wmshell, XtNiconic, &iconic_p);
1663 ew_iconic_p = iconic_p;
1664 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1668 Xt_GET_VALUE (app_shell, XtNgeometry, &geom);
1670 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
1673 frame_flags = XParseGeometry (ew_geom,
1675 &frame_w, &frame_h);
1677 if (first_x_frame_p (f))
1679 /* If this is the first frame created:
1680 ====================================
1682 - Use the ApplicationShell's size/position, if specified.
1683 (This is "Emacs.geometry", or the "-geometry" command line arg.)
1684 - Else use the EmacsFrame's size/position.
1685 (This is "*FRAME-NAME.geometry")
1687 - If the AppShell is iconic, the frame should be iconic.
1689 AppShell comes first so that -geometry always applies to the first
1690 frame created, even if there is an "every frame" entry in the
1693 if (app_flags & (XValue | YValue))
1695 x = app_x; y = app_y;
1696 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
1698 else if (frame_flags & (XValue | YValue))
1700 x = frame_x; y = frame_y;
1701 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1704 if (app_flags & (WidthValue | HeightValue))
1706 w = app_w; h = app_h;
1707 flags |= (app_flags & (WidthValue | HeightValue));
1709 else if (frame_flags & (WidthValue | HeightValue))
1711 w = frame_w; h = frame_h;
1712 flags |= (frame_flags & (WidthValue | HeightValue));
1715 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
1718 Xt_GET_VALUE (app_shell, XtNiconic, &iconic_p);
1721 ew_iconic_p = iconic_p;
1722 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1728 /* If this is not the first frame created:
1729 ========================================
1731 - use the EmacsFrame's size/position if specified
1732 - Otherwise, use the ApplicationShell's size, but not position.
1734 So that means that one can specify the position of the first frame
1735 with "Emacs.geometry" or `-geometry'; but can only specify the
1736 position of subsequent frames with "*FRAME-NAME.geometry".
1738 AppShell comes second so that -geometry does not apply to subsequent
1739 frames when there is an "every frame" entry in the resource db,
1740 but does apply to the first frame.
1742 if (frame_flags & (XValue | YValue))
1744 x = frame_x; y = frame_y;
1745 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1748 if (frame_flags & (WidthValue | HeightValue))
1750 w = frame_w; h = frame_h;
1751 flags |= (frame_flags & (WidthValue | HeightValue));
1753 else if (app_flags & (WidthValue | HeightValue))
1757 flags |= (app_flags & (WidthValue | HeightValue));
1761 x_set_initial_frame_size (f, flags, x, y, w, h);
1765 x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
1769 /* compute height of all top-area widgets */
1770 for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1772 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1773 if (wid && XtIsManaged (wid))
1774 *topbreadth += wid->core.height + 2*wid->core.border_width;
1779 x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
1781 struct frame *f = (struct frame *) client_data;
1782 EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
1783 Dimension width = emst->width;
1784 Dimension height = emst->height;
1785 Widget text = FRAME_X_TEXT_WIDGET (f);
1786 Dimension textbord = text->core.border_width;
1787 Dimension topbreadth;
1788 Position text_x = 0, text_y = 0;
1791 x_get_layout_sizes (f, &topbreadth);
1793 /* first the menubar and psheets ... */
1794 for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1796 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1797 if (wid && XtIsManaged (wid))
1799 Dimension bord = wid->core.border_width;
1800 XtConfigureWidget (wid, 0, text_y,
1801 width - 2*bord, wid->core.height,
1803 text_y += wid->core.height + 2*bord;
1807 #ifdef HAVE_SCROLLBARS
1808 f->scrollbar_y_offset = topbreadth + textbord;
1811 /* finally the text area */
1812 XtConfigureWidget (text, text_x, text_y,
1814 height - text_y - 2*textbord,
1819 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1821 struct frame *f = (struct frame *) client_data;
1822 EmacsManagerQueryGeometryStruct *emst =
1823 (EmacsManagerQueryGeometryStruct *) call_data;
1824 Widget text = FRAME_X_TEXT_WIDGET (f);
1825 Dimension textbord = text->core.border_width;
1826 Dimension topbreadth;
1827 XtWidgetGeometry req, repl;
1828 int mask = emst->request_mode & (CWWidth | CWHeight);
1830 x_get_layout_sizes (f, &topbreadth);
1832 /* Strip away menubar from suggested size, and ask the text widget
1833 what size it wants to be. */
1834 req.request_mode = mask;
1836 req.width = emst->proposed_width - 2*textbord;
1837 if (mask & CWHeight)
1838 req.height = emst->proposed_height - topbreadth - 2*textbord;
1839 XtQueryGeometry (text, &req, &repl);
1841 /* Now add the menubar back again */
1842 emst->proposed_width = repl.width + 2*textbord;
1843 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1846 /* Creates the widgets for a frame.
1847 lisp_window_id is a Lisp description of an X window or Xt
1850 This function does not create or map the windows. (That is
1851 done by x_popup_frame().)
1854 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1857 struct device *d = XDEVICE (f->device);
1858 Visual *visual = DEVICE_X_VISUAL (d);
1859 int depth = DEVICE_X_DEPTH (d);
1860 Colormap cmap = DEVICE_X_COLORMAP (d);
1861 #ifdef EXTERNAL_WIDGET
1862 Window window_id = 0;
1867 Widget text, container, shell;
1868 Widget parentwid = 0;
1869 #ifdef HAVE_MENUBARS
1870 int menubar_visible;
1874 if (STRINGP (f->name))
1875 TO_EXTERNAL_FORMAT (LISP_STRING, f->name,
1876 C_STRING_ALLOCA, name,
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 ();
2489 /* Change from withdrawn state to mapped state. */
2491 x_make_frame_visible (struct frame *f)
2493 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2495 if (!FRAME_VISIBLE_P(f))
2496 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2498 x_raise_frame_1 (f, 0);
2501 /* Change from mapped state to withdrawn state. */
2503 x_make_frame_invisible (struct frame *f)
2505 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2507 if (!FRAME_VISIBLE_P(f))
2510 if (!XWithdrawWindow (display,
2511 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2512 DefaultScreen (display)))
2513 x_cant_notify_wm_error ();
2517 x_frame_visible_p (struct frame *f)
2520 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2521 XWindowAttributes xwa;
2525 This is bad, very bad :-(
2526 It is not compatible with our tristate visible and
2527 it should never ever change the visibility for us, this leads to
2528 the frame-freeze problem under fvwm because with the pager
2530 Mappedness != Viewability != Visibility != Emacs f->visible
2532 This first unequalness is the reason for the frame freezing problem
2533 under fvwm (it happens when the frame is another fvwm-page)
2535 The second unequalness happen when it is on the same fvwm-page
2536 but in an invisible part of the visible screen.
2538 For now we just return the XEmacs internal value --- which might not be up
2539 to date. Is that a problem? ---. Otherwise we should
2540 use async visibility like in standard Emacs.
2543 if (!XGetWindowAttributes (display,
2544 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2548 result = xwa.map_state == IsViewable;
2549 /* In this implementation it should at least be != IsUnmapped
2552 f->visible = result;
2560 x_frame_totally_visible_p (struct frame *f)
2562 return FRAME_X_TOTALLY_VISIBLE_P (f);
2565 /* Change window state from mapped to iconified. */
2567 x_iconify_frame (struct frame *f)
2569 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2571 if (!XIconifyWindow (display,
2572 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2573 DefaultScreen (display)))
2574 x_cant_notify_wm_error ();
2579 /* Sets the X focus to frame f. */
2581 x_focus_on_frame (struct frame *f)
2583 XWindowAttributes xwa;
2584 Widget shell_widget;
2587 assert (FRAME_X_P (f));
2589 shell_widget = FRAME_X_SHELL_WIDGET (f);
2590 if (!XtWindow (shell_widget))
2593 #ifdef EXTERNAL_WIDGET
2594 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2595 ExternalShellSetFocus (shell_widget);
2596 #endif /* EXTERNAL_WIDGET */
2598 /* Do the ICCCM focus change if the window is still visible.
2599 The s->visible flag might not be up-to-date, because we might
2600 not have processed magic events recently. So make a server
2601 round-trip to find out whether it's really mapped right now.
2602 We grab the server to do this, because that's the only way to
2603 eliminate the race condition.
2605 XGrabServer (XtDisplay (shell_widget));
2606 if (XGetWindowAttributes (XtDisplay (shell_widget),
2607 XtWindow (shell_widget),
2609 /* JV: it is bad to change the visibility like this, so we don't for the
2610 moment, at least change_frame_visibility should be called
2611 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2612 but still X-invisible
2613 f->visible = xwa.map_state == IsViewable; */
2614 viewable = xwa.map_state == IsViewable;
2621 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2622 /* Don't explicitly set the focus on this window unless the focus
2623 was on some other window (not PointerRoot). Note that, even when
2624 running a point-to-type window manager like *twm, there is always
2625 a focus window; the window manager maintains that based on the
2626 mouse position. If you set the "NoTitleFocus" option in these
2627 window managers, then the server itself maintains the focus via
2628 PointerRoot, and changing that to focus on the window would make
2629 the window grab the focus. Very bad.
2631 if (focus != PointerRoot)
2633 XSetInputFocus (XtDisplay (shell_widget),
2634 XtWindow (shell_widget),
2636 DEVICE_X_MOUSE_TIMESTAMP
2637 (XDEVICE (FRAME_DEVICE (f))));
2638 XFlush (XtDisplay (shell_widget));
2641 XUngrabServer (XtDisplay (shell_widget));
2642 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2645 /* Destroy the X window of frame S. */
2647 x_delete_frame (struct frame *f)
2651 #ifndef HAVE_WMCOMMAND
2652 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2653 x_wm_maybe_move_wm_command (f);
2654 #endif /* HAVE_WMCOMMAND */
2657 DtDndDropUnregister (FRAME_X_TEXT_WIDGET (f));
2658 #endif /* HAVE_CDE */
2660 assert (FRAME_X_SHELL_WIDGET (f) != 0);
2661 dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
2663 #ifdef EXTERNAL_WIDGET
2664 expect_x_error (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
2665 /* for obscure reasons having (I think) to do with the internal
2666 window-to-widget hierarchy maintained by Xt, we have to call
2667 XtUnrealizeWidget() here. Xt can really suck. */
2668 if (f->being_deleted)
2669 XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
2670 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2671 x_error_occurred_p (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
2673 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2674 /* make sure the windows are really gone! */
2675 /* #### Is this REALLY necessary? */
2677 #endif /* EXTERNAL_WIDGET */
2679 FRAME_X_SHELL_WIDGET (f) = 0;
2681 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2683 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2684 FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0;
2689 xfree (f->frame_data);
2695 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2701 XSETFRAME(frame, frm);
2703 if (EQ (name, Qforeground))
2705 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2708 if (!EQ (color, Vthe_null_color_instance))
2710 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2711 XtSetArg (al[ac], XtNforeground, (void *) fgc.pixel); ac++;
2714 else if (EQ (name, Qbackground))
2716 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2719 if (!EQ (color, Vthe_null_color_instance))
2721 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2722 XtSetArg (al[ac], XtNbackground, (void *) bgc.pixel); ac++;
2725 /* Really crappy way to force the modeline shadows to be
2726 redrawn. But effective. */
2727 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2728 MARK_FRAME_CHANGED (frm);
2730 else if (EQ (name, Qfont))
2732 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2734 if (!EQ (font, Vthe_null_font_instance))
2735 XtSetArg (al[ac], XtNfont,
2736 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2742 XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
2744 #ifdef HAVE_TOOLBARS
2745 /* Setting the background clears the entire frame area
2746 including the toolbar so we force an immediate redraw of
2748 if (EQ (name, Qbackground))
2749 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2750 #endif /* HAVE_TOOLBARS */
2752 /* Set window manager resize increment hints according to
2753 the new character size */
2754 if (EQ (name, Qfont))
2755 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2759 /************************************************************************/
2760 /* initialization */
2761 /************************************************************************/
2764 syms_of_frame_x (void)
2766 defsymbol (&Qwindow_id, "window-id");
2767 defsymbol (&Qx_resource_name, "x-resource-name");
2769 DEFSUBR (Fx_window_id);
2771 DEFSUBR (Fcde_start_drag_internal);
2773 #ifdef HAVE_OFFIX_DND
2774 DEFSUBR (Foffix_start_drag_internal);
2779 console_type_create_frame_x (void)
2782 CONSOLE_HAS_METHOD (x, init_frame_1);
2783 CONSOLE_HAS_METHOD (x, init_frame_2);
2784 CONSOLE_HAS_METHOD (x, init_frame_3);
2785 CONSOLE_HAS_METHOD (x, mark_frame);
2786 CONSOLE_HAS_METHOD (x, focus_on_frame);
2787 CONSOLE_HAS_METHOD (x, delete_frame);
2788 CONSOLE_HAS_METHOD (x, get_mouse_position);
2789 CONSOLE_HAS_METHOD (x, set_mouse_position);
2790 CONSOLE_HAS_METHOD (x, raise_frame);
2791 CONSOLE_HAS_METHOD (x, lower_frame);
2792 CONSOLE_HAS_METHOD (x, make_frame_visible);
2793 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2794 CONSOLE_HAS_METHOD (x, iconify_frame);
2795 CONSOLE_HAS_METHOD (x, set_frame_size);
2796 CONSOLE_HAS_METHOD (x, set_frame_position);
2797 CONSOLE_HAS_METHOD (x, frame_property);
2798 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2799 CONSOLE_HAS_METHOD (x, frame_properties);
2800 CONSOLE_HAS_METHOD (x, set_frame_properties);
2801 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2802 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2803 CONSOLE_HAS_METHOD (x, frame_visible_p);
2804 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2805 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2806 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2807 CONSOLE_HAS_METHOD (x, set_frame_icon);
2808 CONSOLE_HAS_METHOD (x, get_frame_parent);
2809 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2813 vars_of_frame_x (void)
2815 #ifdef EXTERNAL_WIDGET
2816 Fprovide (intern ("external-widget"));
2819 /* this call uses only safe functions from emacs.c */
2820 init_x_prop_symbols ();
2822 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2823 Plist of default frame-creation properties for X frames.
2824 These override what is specified in the resource database and in
2825 `default-frame-plist', but are overridden by the arguments to the
2826 particular call to `make-frame'.
2828 Note: In many cases, properties of a frame are available as specifiers
2829 instead of through the frame-properties mechanism.
2831 Here is a list of recognized frame properties, other than those
2832 documented in `set-frame-properties' (they can be queried and
2833 set at any time, except as otherwise noted):
2835 window-id The X window ID corresponding to the
2836 frame. May be set only at startup, and
2837 only if external widget support was
2838 compiled in; doing so causes the frame
2839 to be created as an "external widget"
2840 in another program that uses an existing
2841 window in the program rather than creating
2843 initially-unmapped If non-nil, the frame will not be visible
2844 when it is created. In this case, you
2845 need to call `make-frame-visible' to make
2847 popup If non-nil, it should be a frame, and this
2848 frame will be created as a "popup" frame
2849 whose parent is the given frame. This
2850 will make the window manager treat the
2851 frame as a dialog box, which may entail
2852 doing different things (e.g. not asking
2853 for positioning, and not iconifying
2854 separate from its parent).
2855 inter-line-space Not currently implemented.
2856 toolbar-shadow-thickness Thickness of toolbar shadows.
2857 background-toolbar-color Color of toolbar background.
2858 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2859 (*Not* specific to the bottom-toolbar.)
2860 top-toolbar-shadow-color Color of top shadows on toolbars.
2861 (*Not* specific to the top-toolbar.)
2862 internal-border-width Width of internal border around text area.
2863 border-width Width of external border around text area.
2864 top Y position (in pixels) of the upper-left
2865 outermost corner of the frame (i.e. the
2866 upper-left of the window-manager
2868 left X position (in pixels) of the upper-left
2869 outermost corner of the frame (i.e. the
2870 upper-left of the window-manager
2872 border-color Color of external border around text area.
2873 cursor-color Color of text cursor.
2875 See also `default-frame-plist', which specifies properties which apply
2876 to all frames, not just X frames.
2878 Vdefault_x_frame_plist = Qnil;
2880 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;