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 GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA ((CONST char *) value, tmp);
665 new_XtValue = (String) tmp;
670 /* ### Caching is device-independent - belongs in update_frame_title. */
671 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
672 if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
675 XtSetArg (al[0], Xt_resource_name, new_XtValue);
676 XtSetArg (al[1], Xt_resource_encoding_name, encoding);
677 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
682 x_set_title_from_bufbyte (struct frame *f, Bufbyte *name)
684 x_set_frame_text_value (f, name, XtNtitle, XtNtitleEncoding);
688 x_set_icon_name_from_bufbyte (struct frame *f, Bufbyte *name)
690 x_set_frame_text_value (f, name, XtNiconName, XtNiconNameEncoding);
693 /* Set the initial frame size as specified. This function is used
694 when the frame's widgets have not yet been realized. In this
695 case, it is not sufficient just to set the width and height of
696 the EmacsFrame widget, because they will be ignored when the
697 widget is realized (instead, the shell's geometry resource is
701 x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
702 unsigned int w, unsigned int h)
704 char shell_geom [255];
707 char uspos = !!(flags & (XValue | YValue));
708 char ussize = !!(flags & (WidthValue | HeightValue));
711 /* assign the correct size to the EmacsFrame widget ... */
712 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
714 /* and also set the WMShell's geometry */
715 (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
716 (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
719 sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
721 sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
723 sprintf (shell_geom, "=%dx%d", w, h);
727 temp = (char *) xmalloc (1 + strlen (shell_geom));
728 strcpy (temp, shell_geom);
729 FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
734 Xt_SET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp);
737 /* Report to X that a frame property of frame S is being set or changed.
738 If the property is not specially recognized, do nothing.
742 x_set_frame_properties (struct frame *f, Lisp_Object plist)
745 Dimension width = 0, height = 0;
746 Bool width_specified_p = False;
747 Bool height_specified_p = False;
748 Bool x_position_specified_p = False;
749 Bool y_position_specified_p = False;
750 Bool internal_border_width_specified = False;
752 Widget w = FRAME_X_TEXT_WIDGET (f);
754 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
756 Lisp_Object prop = Fcar (tail);
757 Lisp_Object val = Fcar (Fcdr (tail));
763 if (XSTRING_LENGTH (prop) == 0)
766 GET_C_STRING_CTEXT_DATA_ALLOCA (prop, extprop);
769 CONST Extbyte *extval;
772 GET_STRING_CTEXT_DATA_ALLOCA (val, extval, extvallen);
773 XtVaSetValues (w, XtVaTypedArg, extprop,
774 XtRString, extval, extvallen + 1,
778 XtVaSetValues (w, XtVaTypedArg, extprop, XtRInt,
779 XINT (val), sizeof (int),
782 else if (SYMBOLP (prop))
784 Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
785 int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
787 if (NILP (prop) || NILP (str))
789 /* Kludge to handle the font property. */
790 if (EQ (prop, Qfont))
792 /* If the value is not a string we silently ignore it. */
795 Lisp_Object frm, font_spec;
798 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
800 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
801 update_frame_face_values (f);
811 /* Kludge the width/height so that we interpret them in characters
812 instead of pixels. Yuck yuck yuck. */
813 if (!strcmp ((char *) XSTRING_DATA (str), "width"))
817 width_specified_p = True;
820 if (!strcmp ((char *) XSTRING_DATA (str), "height"))
824 height_specified_p = True;
827 /* Further kludge the x/y. */
828 if (!strcmp ((char *) XSTRING_DATA (str), "x"))
831 x = (Position) XINT (val);
832 x_position_specified_p = True;
835 if (!strcmp ((char *) XSTRING_DATA (str), "y"))
838 y = (Position) XINT (val);
839 y_position_specified_p = True;
842 /* Have you figured out by now that this entire function is
843 one gigantic kludge? */
844 if (!strcmp ((char *) XSTRING_DATA (str),
845 "internalBorderWidth"))
847 internal_border_width_specified = True;
853 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val));
855 else if (EQ (val, Qt))
857 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/
859 else if (EQ (val, Qnil))
861 Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/
866 XtVaSetValues (w, XtVaTypedArg,
868 (char *) XSTRING_DATA (str),
871 XSTRING_LENGTH (val) + 1,
875 #ifdef HAVE_SCROLLBARS
876 if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth")
877 || !strcmp ((char *) XSTRING_DATA (str),
880 x_update_frame_scrollbars (f);
882 #endif /* HAVE_SCROLLBARS */
886 /* Kludge kludge kludge. We need to deal with the size and position
889 int size_specified_p = width_specified_p || height_specified_p;
890 int position_specified_p = x_position_specified_p ||
891 y_position_specified_p;
893 if (!width_specified_p)
894 width = FRAME_WIDTH (f);
895 if (!height_specified_p)
896 height = FRAME_HEIGHT (f);
898 /* Kludge kludge kludge kludge. */
899 if (position_specified_p &&
900 (!x_position_specified_p || !y_position_specified_p))
903 Widget shell = FRAME_X_SHELL_WIDGET (f);
904 x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
905 (x_position_specified_p ? &dummy : &x),
906 (y_position_specified_p ? &dummy : &y));
908 x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
909 y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
913 if (!f->init_finished)
915 int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
916 (position_specified_p ?
917 XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
920 || position_specified_p
921 || internal_border_width_specified)
922 x_set_initial_frame_size (f, flags, x, y, width, height);
926 if (size_specified_p || internal_border_width_specified)
929 XSETFRAME (frame, f);
930 Fset_frame_size (frame, make_int (width),
931 make_int (height), Qnil);
933 if (position_specified_p)
936 XSETFRAME (frame, f);
937 Fset_frame_position (frame, make_int (x), make_int (y));
943 static int frame_title_format_already_set;
946 maybe_set_frame_title_format (Widget shell)
949 /* Only do this if this is the first X frame we're creating.
951 If the *title resource (or -title option) was specified, then
952 set frame-title-format to its value.
955 if (!frame_title_format_already_set)
957 /* No doubt there's a less stupid way to do this. */
959 XtResource resources [2];
960 results [0] = results [1] = 0;
961 resources [0].resource_name = XtNtitle;
962 resources [0].resource_class = XtCTitle;
963 resources [0].resource_type = XtRString;
964 resources [0].resource_size = sizeof (String);
965 resources [0].resource_offset = 0;
966 resources [0].default_type = XtRString;
967 resources [0].default_addr = 0;
968 resources [1].resource_name = XtNiconName;
969 resources [1].resource_class = XtCIconName;
970 resources [1].resource_type = XtRString;
971 resources [1].resource_size = sizeof (String);
972 resources [1].resource_offset = sizeof (char *);
973 resources [1].default_type = XtRString;
974 resources [1].default_addr = 0;
975 XtGetSubresources (XtParent (shell), (XtPointer) results,
977 shell->core.widget_class->core_class.class_name,
978 resources, XtNumber (resources), 0, 0);
980 Vframe_title_format = build_string (results[0]);
982 Vframe_icon_title_format = build_string (results[1]);
985 frame_title_format_already_set = 1;
992 static Widget CurrentDragWidget = NULL;
993 static XtCallbackRec dnd_convert_cb_rec[2];
994 static XtCallbackRec dnd_destroy_cb_rec[2];
995 static int drag_not_done = 0;
998 x_cde_destroy_callback (Widget widget, XtPointer clientData,
1001 DtDndDragFinishCallbackStruct *dragFinishInfo =
1002 (DtDndDragFinishCallbackStruct *)callData;
1003 DtDndContext *dragData = dragFinishInfo->dragData;
1006 /* free the items */
1007 if (callData != NULL && dragData != NULL)
1009 if (dragData->protocol == DtDND_BUFFER_TRANSFER)
1011 for (i = 0; i < dragData->numItems; i++)
1013 XtFree((char *) dragData->data.buffers[i].bp);
1014 if (dragData->data.buffers[i].name)
1015 XtFree(dragData->data.buffers[i].name);
1020 for (i = 0; i < dragData->numItems; i++)
1021 XtFree(dragData->data.files[i]);
1025 /* free the data string */
1028 CurrentDragWidget = NULL;
1032 x_cde_convert_callback (Widget widget, XtPointer clientData,
1035 DtDndConvertCallbackStruct *convertInfo =
1036 (DtDndConvertCallbackStruct *) callData;
1037 char *textdata = (char *) clientData;
1038 char *textptr = NULL;
1041 if (convertInfo == NULL)
1046 if ((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER
1047 && convertInfo->dragData->protocol != DtDND_FILENAME_TRANSFER) ||
1048 (convertInfo->reason != DtCR_DND_CONVERT_DATA))
1053 for (textptr=textdata, i=0;
1054 i<convertInfo->dragData->numItems;
1055 textptr+=strlen(textptr)+1, i++)
1057 if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER)
1059 convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr);
1060 convertInfo->dragData->data.buffers[i].size = strlen(textptr);
1061 convertInfo->dragData->data.buffers[i].name = NULL;
1065 convertInfo->dragData->data.files[i] = XtNewString(textptr);
1069 convertInfo->status = DtDND_SUCCESS;
1073 abort_current_drag(Lisp_Object arg)
1075 if (CurrentDragWidget && drag_not_done)
1077 XmDragCancel(CurrentDragWidget);
1078 CurrentDragWidget = NULL;
1083 DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 3, 3, 0, /*
1084 Start a CDE drag from a buffer.
1085 First argument is the event that started the drag (must be a
1086 button-press-event),
1087 second arg defines if the data should be treated as a buffer or
1088 a filename transfer (set to nil for buffer transfer),
1089 and the third argument is a list of data strings.
1090 WARNING: can only handle plain/text and file: transfers!
1092 (event, dragtype, dragdata))
1096 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1098 Widget wid = FRAME_X_TEXT_WIDGET (f);
1099 Display *display = XtDisplayOfObject (wid);
1100 struct device *d = get_device_from_display (display);
1101 struct x_device *xd = DEVICE_X_DATA (d);
1102 XWindowAttributes win_attrib;
1103 unsigned int modifier = 0, state = 0;
1105 int numItems = 0, textlen = 0, pos = 0;
1106 struct Lisp_Event *lisp_event = XEVENT(event);
1107 Lisp_Object item = Qnil;
1108 struct gcpro gcpro1;
1110 /* only drag if this is really a press */
1111 if (EVENT_TYPE(lisp_event) != button_press_event
1112 || !LISTP(dragdata))
1118 * not so cross hack that converts a emacs event back to a XEvent
1121 x_event.xbutton.type = ButtonPress;
1122 x_event.xbutton.send_event = False;
1123 x_event.xbutton.display = XtDisplayOfObject(wid);
1124 x_event.xbutton.window = XtWindowOfObject(wid);
1125 x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0);
1126 x_event.xbutton.subwindow = 0;
1127 x_event.xbutton.time = lisp_event->timestamp;
1128 x_event.xbutton.x = lisp_event->event.button.x;
1129 x_event.xbutton.y = lisp_event->event.button.y;
1130 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1131 x_event.xbutton.window,
1134 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1135 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1139 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1140 x_event.xbutton.y_root = lisp_event->event.button.y;
1142 modifier = lisp_event->event.button.modifiers;
1143 if (modifier & MOD_SHIFT) state |= ShiftMask;
1144 if (modifier & MOD_CONTROL) state |= ControlMask;
1145 if (modifier & MOD_META) state |= xd->MetaMask;
1146 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1147 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1148 if (modifier & MOD_ALT) state |= xd->AltMask;
1149 state |= Button1Mask << (lisp_event->event.button.button-1);
1151 x_event.xbutton.state = state;
1152 x_event.xbutton.button = lisp_event->event.button.button;
1153 x_event.xkey.same_screen = True;
1155 /* convert data strings into a big string */
1157 while (!NILP (item))
1159 if (!STRINGP (XCAR (item)))
1164 textlen += XSTRING_LENGTH (XCAR (item)) + 1;
1172 * concatenate all strings given to one large string, with
1173 * \0 as separator. List is ended by \0.
1175 Ctext = (char *)xmalloc (textlen+1);
1179 while (!NILP (item))
1181 if (!STRINGP (XCAR (item)))
1188 strcpy (Ctext+pos, (CONST char *)XSTRING_DATA (XCAR (item)));
1189 pos += XSTRING_LENGTH (XCAR (item)) + 1;
1194 dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
1195 dnd_convert_cb_rec[0].closure = (XtPointer) Ctext;
1196 dnd_convert_cb_rec[1].callback = NULL;
1197 dnd_convert_cb_rec[1].closure = NULL;
1199 dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
1200 dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext;
1201 dnd_destroy_cb_rec[1].callback = NULL;
1202 dnd_destroy_cb_rec[1].closure = NULL;
1205 DtDndDragStart (wid, &x_event,
1206 (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER),
1216 return numItems?Qt:Qnil;
1223 x_cde_transfer_callback (Widget widget, XtPointer clientData,
1226 char *filePath, *hurl;
1228 Lisp_Object frame = Qnil;
1229 Lisp_Object l_type = Qnil;
1230 Lisp_Object l_data = Qnil;
1231 DtDndTransferCallbackStruct *transferInfo = NULL;
1232 struct gcpro gcpro1, gcpro2, gcpro3;
1235 this needs to be changed to the new protocol:
1236 - we need the button, modifier and pointer states to create a
1237 correct misc_user_event
1238 - the data must be converted to the new format (URL/MIME)
1242 transferInfo = (DtDndTransferCallbackStruct *) callData;
1243 if (transferInfo == NULL)
1246 GCPRO3 (frame, l_type, l_data);
1248 frame = make_frame ((struct frame *) clientData);
1250 if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
1252 l_type = Qdragdrop_URL;
1254 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1256 filePath = transferInfo->dropData->data.files[ii];
1257 hurl = dnd_url_hexify_string ((char *)filePath, "file:");
1258 /* ### Mule-izing required */
1259 l_data = Fcons (make_string ((Bufbyte* )hurl,
1265 else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
1267 int speccount = specpdl_depth();
1269 /* Problem: all buffers a treated as text/plain!!!
1270 Solution: Also support DtDND_TEXT_TRANSFER
1271 perhaps implementation of the Motif protocol
1272 (which is the base of CDE) will clear this */
1273 l_type = Qdragdrop_MIME;
1274 record_unwind_protect(abort_current_drag, Qnil);
1276 for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
1278 /* let us forget this name thing for now... */
1279 /* filePath = transferInfo->dropData->data.buffers[ii].name;
1280 path = (filePath == NULL) ? Qnil
1281 : make_string ((Bufbyte *)filePath, strlen (filePath)); */
1282 /* what, if the data is no text, and how can I tell it? */
1283 l_data = Fcons ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1284 make_string ((Bufbyte *)"8bit", 4),
1285 make_string ((Bufbyte *)transferInfo->dropData->data.buffers[ii].bp,
1286 transferInfo->dropData->data.buffers[ii].size) ),
1290 unbind_to(speccount, Qnil);
1292 else /* the other cases: NOOP_TRANSFER */
1295 /* The Problem: no button and mods from CDE... */
1297 enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch,
1298 Fcons (l_type, l_data),
1299 0 /* this is the button */,
1300 0 /* these are the mods */,
1307 #endif /* HAVE_CDE */
1309 #ifdef HAVE_OFFIX_DND
1311 DEFUN ("offix-start-drag-internal", Foffix_start_drag_internal, 2, 3, 0, /*
1312 Start a OffiX drag from a buffer.
1313 First arg is the event that started the drag,
1314 second arg should be some string, and the third
1315 is the type of the data (this should be an int).
1316 The type defaults to DndText (4).
1318 (event, data, dtyp))
1322 struct frame *f = decode_x_frame (Fselected_frame (Qnil));
1324 Widget wid = FRAME_X_TEXT_WIDGET (f);
1325 Display *display = XtDisplayOfObject (wid);
1326 struct device *d = get_device_from_display (display);
1327 struct x_device *xd = DEVICE_X_DATA (d);
1328 XWindowAttributes win_attrib;
1329 unsigned int modifier = 0, state = 0;
1330 char *dnd_data = NULL;
1331 unsigned long dnd_len = 0;
1332 int dnd_typ = DndText, dnd_dealloc = 0;
1333 struct Lisp_Event *lisp_event = XEVENT(event);
1335 /* only drag if this is really a press */
1336 if (EVENT_TYPE(lisp_event) != button_press_event)
1339 /* get the desired type */
1340 if (!NILP (dtyp) && INTP (dtyp))
1341 dnd_typ = XINT (dtyp);
1343 if (dnd_typ == DndFiles)
1345 Lisp_Object run = data;
1348 if (NILP ( Flistp (data)))
1351 /* construct the data from a list of files */
1353 dnd_data = (char *) xmalloc (1);
1357 if (!STRINGP (XCAR (run)))
1362 len = XSTRING_LENGTH (XCAR (run)) + 1;
1363 dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
1364 strcpy (dnd_data + dnd_len - 1, (CONST char *)XSTRING_DATA (XCAR (run)));
1369 dnd_data[dnd_len - 1] = 0; /* the list-ending zero */
1375 if (!STRINGP (data))
1378 /* and what's with MULE data ??? */
1379 dnd_data = (char *)XSTRING_DATA (data);
1380 dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */
1384 /* not so gross hack that converts an emacs event back to a XEvent */
1386 x_event.xbutton.type = ButtonPress;
1387 x_event.xbutton.send_event = False;
1388 x_event.xbutton.display = XtDisplayOfObject(wid);
1389 x_event.xbutton.window = XtWindowOfObject(wid);
1390 x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0);
1391 x_event.xbutton.subwindow = 0;
1392 x_event.xbutton.time = lisp_event->timestamp;
1393 x_event.xbutton.x = lisp_event->event.button.x;
1394 x_event.xbutton.y = lisp_event->event.button.y;
1395 if (Success == XGetWindowAttributes (x_event.xbutton.display,
1396 x_event.xbutton.window,
1399 x_event.xbutton.x_root = win_attrib.x + lisp_event->event.button.x;
1400 x_event.xbutton.y_root = win_attrib.y + lisp_event->event.button.y;
1404 x_event.xbutton.x_root = lisp_event->event.button.x; /* this is wrong */
1405 x_event.xbutton.y_root = lisp_event->event.button.y;
1408 modifier = lisp_event->event.button.modifiers;
1409 if (modifier & MOD_SHIFT) state |= ShiftMask;
1410 if (modifier & MOD_CONTROL) state |= ControlMask;
1411 if (modifier & MOD_META) state |= xd->MetaMask;
1412 if (modifier & MOD_SUPER) state |= xd->SuperMask;
1413 if (modifier & MOD_HYPER) state |= xd->HyperMask;
1414 if (modifier & MOD_ALT) state |= xd->AltMask;
1415 state |= Button1Mask << (lisp_event->event.button.button-1);
1417 x_event.xbutton.state = state;
1418 x_event.xbutton.button = lisp_event->event.button.button;
1419 x_event.xkey.same_screen = True;
1421 DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len);
1425 /* the next thing blocks everything... */
1426 if (DndHandleDragging(wid, &x_event))
1432 #endif /* HAVE_OFFIX_DND */
1435 /************************************************************************/
1436 /* widget creation */
1437 /************************************************************************/
1439 /* The widget hierarchy is
1441 argv[0] shell container FRAME-NAME
1442 ApplicationShell EmacsShell EmacsManager EmacsFrame
1444 We accept geometry specs in this order:
1446 *FRAME-NAME.geometry
1447 *EmacsFrame.geometry
1450 Other possibilities for widget hierarchies might be
1452 argv[0] frame container FRAME-NAME
1453 ApplicationShell EmacsShell EmacsManager EmacsFrame
1455 argv[0] FRAME-NAME container FRAME-NAME
1456 ApplicationShell EmacsShell EmacsManager EmacsFrame
1458 argv[0] FRAME-NAME container emacsTextPane
1459 ApplicationShell EmacsShell EmacsManager EmacsFrame
1461 #ifdef EXTERNAL_WIDGET
1462 The ExternalShell widget is simply a replacement for the Shell widget
1463 which is able to deal with using an externally-supplied window instead
1464 of always creating its own.
1469 #ifdef EXTERNAL_WIDGET
1472 is_valid_window (Window w, struct device *d)
1474 XWindowAttributes xwa;
1475 Display *dpy = DEVICE_X_DISPLAY (d);
1477 expect_x_error (dpy);
1478 XGetWindowAttributes (dpy, w, &xwa);
1479 return !x_error_occurred_p (dpy);
1482 #endif /* EXTERNAL_WIDGET */
1484 /* This sends a synthetic mouse-motion event to the frame, if the mouse
1485 is over the frame. This ensures that the cursor gets set properly
1486 before the user moves the mouse for the first time. */
1489 x_send_synthetic_mouse_event (struct frame *f)
1491 /* #### write this function. */
1495 first_x_frame_p (struct frame *f)
1497 Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
1498 while (!NILP (rest) &&
1499 (f == XFRAME (XCAR (rest)) ||
1500 !FRAME_X_P (XFRAME (XCAR (rest)))))
1505 /* Figure out what size the EmacsFrame widget should initially be,
1506 and set it. Should be called after the default font has been
1507 determined but before the widget has been realized. */
1510 x_initialize_frame_size (struct frame *f)
1512 /* Geometry of the AppShell */
1516 unsigned int app_w = 0;
1517 unsigned int app_h = 0;
1519 /* Geometry of the EmacsFrame */
1520 int frame_flags = 0;
1523 unsigned int frame_w = 0;
1524 unsigned int frame_h = 0;
1526 /* Hairily merged geometry */
1529 unsigned int w = 80;
1530 unsigned int h = 40;
1533 char *geom = 0, *ew_geom = 0;
1534 Boolean iconic_p = False, ew_iconic_p = False;
1536 Widget wmshell = FRAME_X_SHELL_WIDGET (f);
1537 /* #### This may not be an ApplicationShell any more, with the 'popup
1539 Widget app_shell = XtParent (wmshell);
1540 Widget ew = FRAME_X_TEXT_WIDGET (f);
1542 /* set the position of the frame's root window now. When the
1543 frame was created, the position was initialized to (0,0). */
1545 struct window *win = XWINDOW (f->root_window);
1547 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1548 WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
1550 if (!NILP (f->minibuffer_window))
1552 win = XWINDOW (f->minibuffer_window);
1553 WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
1557 #ifdef EXTERNAL_WIDGET
1558 /* If we're an external widget, then the size of the frame is predetermined
1559 (by the client) and is not our decision to make. */
1560 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1565 /* #### this junk has not been tested; therefore it's
1566 probably wrong. Doesn't really matter at this point because
1567 currently all frames are either top-level or external widgets. */
1569 /* If we're not our own top-level window, then we shouldn't go messing around
1570 with top-level shells or "Emacs.geometry" or any such stuff. Therefore,
1571 we do as follows to determine the size of the frame:
1573 1) If a value for the frame's "geometry" resource was specified, then
1574 use it. (This specifies a size in characters.)
1575 2) Else, if the "width" and "height" resources were specified, then
1576 leave them alone. (This is a value in pixels. Sorry, we can't break
1577 Xt conventions here.)
1578 3) Else, assume a size of 64x12. (This is somewhat arbitrary, but
1579 it's unlikely that a size of 80x40 is desirable because we're probably
1580 inside of a dialog box.)
1582 Set the widget's x, y, height, and width as determined. Don't set the
1583 top-level container widget, because we don't necessarily know what it
1584 is. (Assume it is smart and pays attention to our values.)
1587 if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
1589 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1591 frame_flags = XParseGeometry (ew_geom,
1593 &frame_w, &frame_h);
1594 if (! (frame_flags & (WidthValue | HeightValue)))
1597 XtSetArg (al [0], XtNwidth, &frame_w);
1598 XtSetArg (al [1], XtNheight, &frame_h);
1599 XtGetValues (ew, al, 2);
1600 if (!frame_w && !frame_h)
1604 frame_flags |= WidthValue | HeightValue;
1607 if (frame_flags & (WidthValue | HeightValue))
1608 EmacsFrameSetCharSize (ew, frame_w, frame_h);
1609 if (frame_flags & (XValue | YValue))
1612 XtSetArg (al [0], XtNwidth, &frame_w);
1613 XtSetArg (al [1], XtNheight, &frame_h);
1614 XtGetValues (ew, al, 2);
1616 if (frame_flags & XNegative)
1618 if (frame_flags & YNegative)
1621 XtSetArg (al [0], XtNx, frame_x);
1622 XtSetArg (al [1], XtNy, frame_y);
1623 XtSetValues (ew, al, 2);
1629 /* OK, we're a top-level shell. */
1631 if (!XtIsWMShell (wmshell))
1634 /* If the EmacsFrame doesn't have a geometry but the shell does,
1635 treat that as the geometry of the frame.
1636 (Is this bogus? I'm not sure.) */
1638 Xt_GET_VALUE (ew, XtNgeometry, &ew_geom);
1641 Xt_GET_VALUE (wmshell, XtNgeometry, &geom);
1645 Xt_SET_VALUE (ew, XtNgeometry, ew_geom);
1649 /* If the Shell is iconic, then the EmacsFrame is iconic.
1650 (Is this bogus? I'm not sure.) */
1651 Xt_GET_VALUE (ew, XtNiconic, &ew_iconic_p);
1654 Xt_GET_VALUE (wmshell, XtNiconic, &iconic_p);
1657 ew_iconic_p = iconic_p;
1658 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1662 Xt_GET_VALUE (app_shell, XtNgeometry, &geom);
1664 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
1667 frame_flags = XParseGeometry (ew_geom,
1669 &frame_w, &frame_h);
1671 if (first_x_frame_p (f))
1673 /* If this is the first frame created:
1674 ====================================
1676 - Use the ApplicationShell's size/position, if specified.
1677 (This is "Emacs.geometry", or the "-geometry" command line arg.)
1678 - Else use the EmacsFrame's size/position.
1679 (This is "*FRAME-NAME.geometry")
1681 - If the AppShell is iconic, the frame should be iconic.
1683 AppShell comes first so that -geometry always applies to the first
1684 frame created, even if there is an "every frame" entry in the
1687 if (app_flags & (XValue | YValue))
1689 x = app_x; y = app_y;
1690 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
1692 else if (frame_flags & (XValue | YValue))
1694 x = frame_x; y = frame_y;
1695 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1698 if (app_flags & (WidthValue | HeightValue))
1700 w = app_w; h = app_h;
1701 flags |= (app_flags & (WidthValue | HeightValue));
1703 else if (frame_flags & (WidthValue | HeightValue))
1705 w = frame_w; h = frame_h;
1706 flags |= (frame_flags & (WidthValue | HeightValue));
1709 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
1712 Xt_GET_VALUE (app_shell, XtNiconic, &iconic_p);
1715 ew_iconic_p = iconic_p;
1716 Xt_SET_VALUE (ew, XtNiconic, iconic_p);
1722 /* If this is not the first frame created:
1723 ========================================
1725 - use the EmacsFrame's size/position if specified
1726 - Otherwise, use the ApplicationShell's size, but not position.
1728 So that means that one can specify the position of the first frame
1729 with "Emacs.geometry" or `-geometry'; but can only specify the
1730 position of subsequent frames with "*FRAME-NAME.geometry".
1732 AppShell comes second so that -geometry does not apply to subsequent
1733 frames when there is an "every frame" entry in the resource db,
1734 but does apply to the first frame.
1736 if (frame_flags & (XValue | YValue))
1738 x = frame_x; y = frame_y;
1739 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
1742 if (frame_flags & (WidthValue | HeightValue))
1744 w = frame_w; h = frame_h;
1745 flags |= (frame_flags & (WidthValue | HeightValue));
1747 else if (app_flags & (WidthValue | HeightValue))
1751 flags |= (app_flags & (WidthValue | HeightValue));
1755 x_set_initial_frame_size (f, flags, x, y, w, h);
1759 x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
1763 /* compute height of all top-area widgets */
1764 for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1766 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1767 if (wid && XtIsManaged (wid))
1768 *topbreadth += wid->core.height + 2*wid->core.border_width;
1773 x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
1775 struct frame *f = (struct frame *) client_data;
1776 EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
1777 Dimension width = emst->width;
1778 Dimension height = emst->height;
1779 Widget text = FRAME_X_TEXT_WIDGET (f);
1780 Dimension textbord = text->core.border_width;
1781 Dimension topbreadth;
1782 Position text_x = 0, text_y = 0;
1785 x_get_layout_sizes (f, &topbreadth);
1787 /* first the menubar and psheets ... */
1788 for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
1790 Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
1791 if (wid && XtIsManaged (wid))
1793 Dimension bord = wid->core.border_width;
1794 XtConfigureWidget (wid, 0, text_y,
1795 width - 2*bord, wid->core.height,
1797 text_y += wid->core.height + 2*bord;
1801 #ifdef HAVE_SCROLLBARS
1802 f->scrollbar_y_offset = topbreadth + textbord;
1805 /* finally the text area */
1806 XtConfigureWidget (text, text_x, text_y,
1808 height - text_y - 2*textbord,
1813 x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
1815 struct frame *f = (struct frame *) client_data;
1816 EmacsManagerQueryGeometryStruct *emst =
1817 (EmacsManagerQueryGeometryStruct *) call_data;
1818 Widget text = FRAME_X_TEXT_WIDGET (f);
1819 Dimension textbord = text->core.border_width;
1820 Dimension topbreadth;
1821 XtWidgetGeometry req, repl;
1822 int mask = emst->request_mode & (CWWidth | CWHeight);
1824 x_get_layout_sizes (f, &topbreadth);
1826 /* Strip away menubar from suggested size, and ask the text widget
1827 what size it wants to be. */
1828 req.request_mode = mask;
1830 req.width = emst->proposed_width - 2*textbord;
1831 if (mask & CWHeight)
1832 req.height = emst->proposed_height - topbreadth - 2*textbord;
1833 XtQueryGeometry (text, &req, &repl);
1835 /* Now add the menubar back again */
1836 emst->proposed_width = repl.width + 2*textbord;
1837 emst->proposed_height = repl.height + topbreadth + 2*textbord;
1840 /* Creates the widgets for a frame.
1841 lisp_window_id is a Lisp description of an X window or Xt
1844 This function does not create or map the windows. (That is
1845 done by x_popup_frame().)
1848 x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
1851 struct device *d = XDEVICE (f->device);
1852 Visual *visual = DEVICE_X_VISUAL (d);
1853 int depth = DEVICE_X_DEPTH (d);
1854 Colormap cmap = DEVICE_X_COLORMAP (d);
1855 #ifdef EXTERNAL_WIDGET
1856 Window window_id = 0;
1861 Widget text, container, shell;
1862 Widget parentwid = 0;
1863 #ifdef HAVE_MENUBARS
1864 int menubar_visible;
1868 if (STRINGP (f->name))
1869 GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, name);
1873 /* The widget hierarchy is
1875 argv[0] shell pane FRAME-NAME
1876 ApplicationShell EmacsShell EmacsManager EmacsFrame
1878 (the type of the shell is ExternalShell if this frame is running
1879 in another client's window)
1881 However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
1882 Normally such shells have name/class shellname/appclass, which in this
1883 case would be "shell/Emacs" instead of "frame-name/Emacs". We could
1884 also get around this by naming the shell "frame-name", but that would
1885 be confusing because the text area (the EmacsFrame widget inferior of
1886 the shell) is also called that. So we just set the WM_CLASS property.
1889 #ifndef EXTERNAL_WIDGET
1890 if (!NILP (lisp_window_id))
1891 error ("support for external widgets was not enabled at compile-time");
1893 if (!NILP (lisp_window_id))
1897 CHECK_STRING (lisp_window_id);
1898 string = (char *) XSTRING_DATA (lisp_window_id);
1899 if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
1900 sscanf (string+2, "%lxu", &window_id);
1902 else if (string[0] == 'w')
1904 sscanf (string+1, "%x", &parent_widget);
1906 window_id = XtWindow (parent_widget);
1910 sscanf (string, "%lu", &window_id);
1911 if (!is_valid_window (window_id, d))
1912 error ("Invalid window %lu", (unsigned long) window_id);
1913 FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
1915 #endif /* EXTERNAL_WIDGET */
1916 FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
1919 XtSetArg (al[ac], XtNallowShellResize, True); ac++;
1920 #ifdef LWLIB_USES_MOTIF
1921 /* Motif sucks beans. Without this in here, it will delete the window
1922 out from under us when it receives a WM_DESTROY_WINDOW message
1924 XtSetArg (al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
1927 #ifdef EXTERNAL_WIDGET
1930 XtSetArg (al[ac], XtNwindow, window_id); ac++;
1933 #endif /* EXTERNAL_WIDGET */
1935 XtSetArg (al[ac], XtNinput, True); ac++;
1936 XtSetArg (al[ac], XtNminWidthCells, 10); ac++;
1937 XtSetArg (al[ac], XtNminHeightCells, 1); ac++;
1938 XtSetArg (al[ac], XtNvisual, visual); ac++;
1939 XtSetArg (al[ac], XtNdepth, depth); ac++;
1940 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1945 parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
1946 XtSetArg (al[ac], XtNtransientFor, parentwid); ac++;
1949 shell = XtCreatePopupShell ("shell",
1951 #ifdef EXTERNAL_WIDGET
1952 window_id ? externalShellWidgetClass :
1954 parentwid ? transientEmacsShellWidgetClass :
1955 topLevelEmacsShellWidgetClass
1957 parentwid ? parentwid :
1958 DEVICE_XT_APP_SHELL (d),
1960 FRAME_X_SHELL_WIDGET (f) = shell;
1961 maybe_set_frame_title_format (shell);
1963 /* Create the manager widget */
1965 XtSetArg (al[ac], XtNvisual, visual); ac++;
1966 XtSetArg (al[ac], XtNdepth, depth); ac++;
1967 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1969 container = XtCreateWidget ("container",
1970 emacsManagerWidgetClass, shell, al, ac);
1971 FRAME_X_CONTAINER_WIDGET (f) = container;
1972 XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
1974 XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
1977 /* Create the text area */
1979 XtSetArg (al[ac], XtNvisual, visual); ac++;
1980 XtSetArg (al[ac], XtNdepth, depth); ac++;
1981 XtSetArg (al[ac], XtNcolormap, cmap); ac++;
1982 XtSetArg (al[ac], XtNborderWidth, 0); ac++; /* should this be settable? */
1983 XtSetArg (al[ac], XtNemacsFrame, f); ac++;
1984 text = XtCreateWidget (name, emacsFrameClass, container, al, ac);
1985 FRAME_X_TEXT_WIDGET (f) = text;
1987 #ifdef HAVE_MENUBARS
1988 /* Create the initial menubar widget. */
1989 menubar_visible = x_initialize_frame_menubar (f);
1990 FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
1991 FRAME_X_NUM_TOP_WIDGETS (f) = 1;
1993 if (menubar_visible)
1994 XtManageChild (menubar);
1995 #endif /* HAVE_MENUBARS */
1996 XtManageChild (text);
1997 XtManageChild (container);
2000 /* We used to call XtPopup() in x_popup_frame, but that doesn't give
2001 you control over whether the widget is initially mapped or not
2002 because XtPopup() makes an unconditional call to XMapRaised().
2003 Boy, those Xt designers were clever.
2005 When we first removed it we only kept the XtRealizeWidget call in
2006 XtPopup. For everything except HP's that was enough. For HP's,
2007 though, the failure to call the popup callbacks resulted in XEmacs
2008 not accepting any input. Bizarre but true. Stupid but true.
2010 So, in case there are any other gotchas floating out there along
2011 the same lines I've duplicated the majority of XtPopup here. It
2012 assumes no grabs and that the widget is not already popped up, both
2013 valid assumptions for the one place this is called from. */
2015 xemacs_XtPopup (Widget widget)
2017 ShellWidget shell_widget = (ShellWidget) widget;
2018 XtGrabKind call_data = XtGrabNone;
2020 XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data);
2022 shell_widget->shell.popped_up = TRUE;
2023 shell_widget->shell.grab_kind = XtGrabNone;
2024 shell_widget->shell.spring_loaded = False;
2026 if (shell_widget->shell.create_popup_child_proc != NULL)
2027 (*(shell_widget->shell.create_popup_child_proc))(widget);
2029 /* The XtSetValues below are not in XtPopup menu. We just want to
2030 make absolutely sure... */
2031 Xt_SET_VALUE (widget, XtNmappedWhenManaged, False);
2032 XtRealizeWidget (widget);
2033 Xt_SET_VALUE (widget, XtNmappedWhenManaged, True);
2036 /* create the windows for the specified frame and display them.
2037 Note that the widgets have already been created, and any
2038 necessary geometry calculations have already been done. */
2040 x_popup_frame (struct frame *f)
2042 Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
2043 Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
2044 struct device *d = XDEVICE (FRAME_DEVICE (f));
2046 /* Before mapping the window, make sure that the WMShell's notion of
2047 whether it should be iconified is synchronized with the EmacsFrame's
2050 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2051 x_wm_set_shell_iconic_p (shell_widget,
2052 ((EmacsFrame) frame_widget)
2053 ->emacs_frame.iconic);
2055 xemacs_XtPopup (shell_widget);
2057 if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
2058 XtMapWidget (shell_widget);
2061 /* We may have set f->visible to 1 in x_init_frame(), so undo
2063 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
2067 #ifdef EXTERNAL_WIDGET
2068 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2069 ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
2072 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2074 /* tell the window manager about us. */
2075 x_wm_store_class_hints (shell_widget, XtName (frame_widget));
2077 #ifndef HAVE_WMCOMMAND
2078 x_wm_maybe_store_wm_command (f);
2079 #endif /* HAVE_WMCOMMAND */
2081 x_wm_hack_wm_protocols (shell_widget);
2086 #endif /* HAVE_XIM */
2089 /* Allow XEmacs to respond to EditRes requests. See the O'Reilly Xt */
2090 /* Intrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
2092 XtAddEventHandler (shell_widget, /* the shell widget in question */
2093 (EventMask) NoEventMask,/* OR with existing mask */
2094 True, /* called on non-maskable events? */
2095 (XtEventHandler) _XEditResCheckMessages, /* the handler */
2097 #endif /* HACK_EDITRES */
2101 XtCallbackRec dnd_transfer_cb_rec[2];
2103 dnd_transfer_cb_rec[0].callback = x_cde_transfer_callback;
2104 dnd_transfer_cb_rec[0].closure = (XtPointer) f;
2105 dnd_transfer_cb_rec[1].callback = NULL;
2106 dnd_transfer_cb_rec[1].closure = NULL;
2108 DtDndVaDropRegister (FRAME_X_TEXT_WIDGET (f),
2109 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
2110 XmDROP_COPY, dnd_transfer_cb_rec,
2111 DtNtextIsBuffer, True,
2112 DtNregisterChildren, True,
2113 DtNpreserveRegistration, False,
2116 #endif /* HAVE_CDE */
2118 /* Do a stupid property change to force the server to generate a
2119 propertyNotify event so that the event_stream server timestamp will
2120 be initialized to something relevant to the time we created the window.
2122 XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
2123 DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
2124 (unsigned char*) NULL, 0);
2126 x_send_synthetic_mouse_event (f);
2130 allocate_x_frame_struct (struct frame *f)
2132 /* zero out all slots. */
2133 f->frame_data = xnew_and_zero (struct x_frame);
2135 /* yeah, except the lisp ones */
2136 FRAME_X_ICON_PIXMAP (f) = Qnil;
2137 FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
2141 /************************************************************************/
2142 /* Lisp functions */
2143 /************************************************************************/
2146 x_init_frame_1 (struct frame *f, Lisp_Object props)
2148 /* This function can GC */
2149 Lisp_Object device = FRAME_DEVICE (f);
2150 Lisp_Object lisp_window_id = Fplist_get (props, Qwindow_id, Qnil);
2151 Lisp_Object popup = Fplist_get (props, Qpopup, Qnil);
2156 popup = Fselected_frame (device);
2157 CHECK_LIVE_FRAME (popup);
2158 if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
2159 signal_simple_error_2 ("Parent must be on same device as frame",
2164 * Previously we set this only if NILP (DEVICE_SELECTED_FRAME (d))
2165 * to make sure that messages were displayed as soon as possible
2166 * if we're creating the first frame on a device. But it is
2167 * better to just set this all the time, so that when a new frame
2168 * is created that covers the selected frame, echo area status
2169 * messages can still be seen. f->visible is reset later if the
2170 * initially-unmapped property is found to be non-nil in the
2175 allocate_x_frame_struct (f);
2176 x_create_widgets (f, lisp_window_id, popup);
2180 x_init_frame_2 (struct frame *f, Lisp_Object props)
2182 /* Set up the values of the widget/frame. A case could be made for putting
2183 this inside of the widget's initialize method. */
2185 update_frame_face_values (f);
2186 x_initialize_frame_size (f);
2188 * update_frame_title() can't be done here, because some of the
2189 * modeline specs depend on the frame's device having a selected
2190 * frame, and that may not have been set up yet. The redisplay
2191 * will update the frame title anyway, so nothing is lost.
2193 * It turns out it gives problems with FVWMs name based mapping.
2194 * We'll just need to be careful in the modeline specs.
2196 update_frame_title (f);
2200 x_init_frame_3 (struct frame *f)
2202 /* Pop up the frame. */
2208 x_mark_frame (struct frame *f)
2210 mark_object (FRAME_X_ICON_PIXMAP (f));
2211 mark_object (FRAME_X_ICON_PIXMAP_MASK (f));
2215 x_set_frame_icon (struct frame *f)
2217 Pixmap x_pixmap, x_mask;
2219 if (IMAGE_INSTANCEP (f->icon)
2220 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
2222 x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (f->icon);
2223 x_mask = XIMAGE_INSTANCE_X_MASK (f->icon);
2231 /* Store the X data into the widget. */
2234 XtSetArg (al [0], XtNiconPixmap, x_pixmap);
2235 XtSetArg (al [1], XtNiconMask, x_mask);
2236 XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2);
2241 x_set_frame_pointer (struct frame *f)
2243 XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
2244 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2245 XIMAGE_INSTANCE_X_CURSOR (f->pointer));
2246 XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
2250 x_get_frame_parent (struct frame *f)
2252 Widget parentwid = 0;
2254 Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), XtNtransientFor, &parentwid);
2255 /* find the frame whose wid is parentwid */
2258 Lisp_Object frmcons;
2259 DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
2261 Lisp_Object frame = XCAR (frmcons);
2262 if (FRAME_X_SHELL_WIDGET (XFRAME (frame)) == parentwid)
2269 DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
2270 Get the ID of the X11 window.
2271 This gives us a chance to manipulate the Emacs window from within a
2272 different program. Since the ID is an unsigned long, we return it as
2278 struct frame *f = decode_x_frame (frame);
2280 sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
2281 return build_string (str);
2285 /************************************************************************/
2286 /* manipulating the X window */
2287 /************************************************************************/
2290 x_set_frame_position (struct frame *f, int xoff, int yoff)
2292 Widget w = FRAME_X_SHELL_WIDGET (f);
2293 Display *dpy = XtDisplay (w);
2294 Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
2295 Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
2296 Dimension shell_w, shell_h, shell_bord;
2300 XtSetArg (al [0], XtNwidth, &shell_w);
2301 XtSetArg (al [1], XtNheight, &shell_h);
2302 XtSetArg (al [2], XtNborderWidth, &shell_bord);
2303 XtGetValues (w, al, 3);
2306 xoff >= 0 && yoff >= 0 ? NorthWestGravity :
2307 xoff >= 0 ? SouthWestGravity :
2308 yoff >= 0 ? NorthEastGravity :
2311 xoff += frame_w - shell_w - 2*shell_bord;
2313 yoff += frame_h - shell_h - 2*shell_bord;
2315 /* Update the hints so that, if this window is currently iconified, it will
2316 come back at the right place. We can't look at s->visible to determine
2317 whether it is iconified because it might not be up-to-date yet (the queue
2318 might not be processed). */
2319 XtSetArg (al [0], XtNwinGravity, win_gravity);
2320 XtSetArg (al [1], XtNx, xoff);
2321 XtSetArg (al [2], XtNy, yoff);
2322 XtSetValues (w, al, 3);
2324 /* Sometimes you will find that
2326 (set-frame-position (selected-frame) -50 -50)
2328 doesn't put the frame where you expect it to: i.e. it's closer to
2329 the lower-right corner than it should be, and it appears that the
2330 size of the WM decorations was not taken into account. This is
2331 *not* a problem with this function. Both mwm and twm have bugs
2332 in handling this situation. (mwm ignores the window gravity and
2333 always assumes NorthWest, except the first time you map the
2334 window; twm gets things almost right, but forgets to account for
2335 the border width of the top-level window.) This function does
2336 what it's supposed to according to the ICCCM, and I'm not about
2337 to hack around window-manager bugs. */
2340 /* This is not necessary under either mwm or twm */
2341 x_wm_mark_shell_position_user_specified (w);
2345 /* Call this to change the size of frame S's x-window. */
2348 x_set_frame_size (struct frame *f, int cols, int rows)
2350 EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
2352 /* this is not correct. x_set_frame_size() is called from
2353 Fset_frame_size(), which may or may not have been called
2354 by the user (e.g. update_EmacsFrame() calls it when the font
2355 changes). For now, don't bother with getting this right. */
2356 x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
2361 x_set_mouse_position (struct window *w, int x, int y)
2363 struct frame *f = XFRAME (w->frame);
2365 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2366 XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
2367 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
2371 x_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
2373 Display *display = DEVICE_X_DISPLAY (d);
2374 Window child_window;
2379 unsigned int keys_and_buttons;
2382 if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
2383 &root_window, &child_window, &root_x, &root_y,
2384 &win_x, &win_y, &keys_and_buttons) == False)
2387 if (child_window == None)
2388 return 0; /* not over any window. */
2393 if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
2394 &win_x, &win_y, &child_window) == False)
2398 if (child_window == None)
2402 /* At this point, win is the innermost window containing the pointer
2403 and win_x and win_y are the coordinates of that window. */
2404 f = x_any_window_to_frame (d, win);
2407 XSETFRAME (*frame, f);
2409 if (XTranslateCoordinates (display, win,
2410 XtWindow (FRAME_X_TEXT_WIDGET (f)),
2411 win_x, win_y, x, y, &child_window) == False)
2419 x_cant_notify_wm_error (void)
2421 error ("Can't notify window manager of iconification.");
2424 /* Raise frame F. */
2426 x_raise_frame_1 (struct frame *f, int force)
2428 if (FRAME_VISIBLE_P (f) || force)
2430 Widget bottom_dialog;
2433 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2434 Window emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
2436 /* first raises all the dialog boxes, then put emacs just below the
2437 * bottom most dialog box */
2438 bottom_dialog = lw_raise_all_pop_up_widgets ();
2439 if (bottom_dialog && XtWindow (bottom_dialog))
2441 xwc.sibling = XtWindow (bottom_dialog);
2442 xwc.stack_mode = Below;
2443 flags = CWSibling | CWStackMode;
2447 xwc.stack_mode = Above;
2448 flags = CWStackMode;
2451 if (!XReconfigureWMWindow (display, emacs_window,
2452 DefaultScreen (display),
2454 x_cant_notify_wm_error ();
2459 x_raise_frame (struct frame *f)
2461 x_raise_frame_1 (f, 1);
2464 /* Lower frame F. */
2466 x_lower_frame (struct frame *f)
2468 if (FRAME_VISIBLE_P (f))
2470 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2472 unsigned int flags = CWStackMode;
2474 xwc.stack_mode = Below;
2475 if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
2476 DefaultScreen (display), flags, &xwc))
2477 x_cant_notify_wm_error ();
2481 /* Change from withdrawn state to mapped state. */
2483 x_make_frame_visible (struct frame *f)
2485 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2487 if (!FRAME_VISIBLE_P(f))
2488 XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
2490 x_raise_frame_1 (f, 0);
2493 /* Change from mapped state to withdrawn state. */
2495 x_make_frame_invisible (struct frame *f)
2497 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2499 if (!FRAME_VISIBLE_P(f))
2502 if (!XWithdrawWindow (display,
2503 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2504 DefaultScreen (display)))
2505 x_cant_notify_wm_error ();
2509 x_frame_visible_p (struct frame *f)
2512 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2513 XWindowAttributes xwa;
2517 This is bad, very bad :-(
2518 It is not compatible with our tristate visible and
2519 it should never ever change the visibility for us, this leads to
2520 the frame-freeze problem under fvwm because with the pager
2522 Mappedness != Viewability != Visibility != Emacs f->visible
2524 This first unequalness is the reason for the frame freezing problem
2525 under fvwm (it happens when the frame is another fvwm-page)
2527 The second unequalness happen when it is on the same fvwm-page
2528 but in an invisible part of the visible screen.
2530 For now we just return the XEmacs internal value --- which might not be up
2531 to date. Is that a problem? ---. Otherwise we should
2532 use async visibility like in standard Emacs.
2535 if (!XGetWindowAttributes (display,
2536 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2540 result = xwa.map_state == IsViewable;
2541 /* In this implementation it should at least be != IsUnmapped
2544 f->visible = result;
2552 x_frame_totally_visible_p (struct frame *f)
2554 return FRAME_X_TOTALLY_VISIBLE_P (f);
2557 /* Change window state from mapped to iconified. */
2559 x_iconify_frame (struct frame *f)
2561 Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
2563 if (!XIconifyWindow (display,
2564 XtWindow (FRAME_X_SHELL_WIDGET (f)),
2565 DefaultScreen (display)))
2566 x_cant_notify_wm_error ();
2571 /* Sets the X focus to frame f. */
2573 x_focus_on_frame (struct frame *f)
2575 XWindowAttributes xwa;
2576 Widget shell_widget;
2579 assert (FRAME_X_P (f));
2581 shell_widget = FRAME_X_SHELL_WIDGET (f);
2582 if (!XtWindow (shell_widget))
2585 #ifdef EXTERNAL_WIDGET
2586 if (FRAME_X_EXTERNAL_WINDOW_P (f))
2587 ExternalShellSetFocus (shell_widget);
2588 #endif /* EXTERNAL_WIDGET */
2590 /* Do the ICCCM focus change if the window is still visible.
2591 The s->visible flag might not be up-to-date, because we might
2592 not have processed magic events recently. So make a server
2593 round-trip to find out whether it's really mapped right now.
2594 We grab the server to do this, because that's the only way to
2595 eliminate the race condition.
2597 XGrabServer (XtDisplay (shell_widget));
2598 if (XGetWindowAttributes (XtDisplay (shell_widget),
2599 XtWindow (shell_widget),
2601 /* JV: it is bad to change the visibility like this, so we don't for the
2602 moment, at least change_frame_visibility should be called
2603 Note also that under fvwm a frame can be Viewable (and thus Mapped)
2604 but still X-invisible
2605 f->visible = xwa.map_state == IsViewable; */
2606 viewable = xwa.map_state == IsViewable;
2613 XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
2614 /* Don't explicitly set the focus on this window unless the focus
2615 was on some other window (not PointerRoot). Note that, even when
2616 running a point-to-type window manager like *twm, there is always
2617 a focus window; the window manager maintains that based on the
2618 mouse position. If you set the "NoTitleFocus" option in these
2619 window managers, then the server itself maintains the focus via
2620 PointerRoot, and changing that to focus on the window would make
2621 the window grab the focus. Very bad.
2623 if (focus != PointerRoot)
2625 XSetInputFocus (XtDisplay (shell_widget),
2626 XtWindow (shell_widget),
2628 DEVICE_X_MOUSE_TIMESTAMP
2629 (XDEVICE (FRAME_DEVICE (f))));
2630 XFlush (XtDisplay (shell_widget));
2633 XUngrabServer (XtDisplay (shell_widget));
2634 XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
2637 /* Destroy the X window of frame S. */
2639 x_delete_frame (struct frame *f)
2643 #ifndef HAVE_WMCOMMAND
2644 if (FRAME_X_TOP_LEVEL_FRAME_P (f))
2645 x_wm_maybe_move_wm_command (f);
2646 #endif /* HAVE_WMCOMMAND */
2649 DtDndDropUnregister (FRAME_X_TEXT_WIDGET (f));
2650 #endif /* HAVE_CDE */
2652 assert (FRAME_X_SHELL_WIDGET (f) != 0);
2653 dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
2655 #ifdef EXTERNAL_WIDGET
2656 expect_x_error (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
2657 /* for obscure reasons having (I think) to do with the internal
2658 window-to-widget hierarchy maintained by Xt, we have to call
2659 XtUnrealizeWidget() here. Xt can really suck. */
2660 if (f->being_deleted)
2661 XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
2662 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2663 x_error_occurred_p (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
2665 XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
2666 /* make sure the windows are really gone! */
2667 /* ### Is this REALLY necessary? */
2669 #endif /* EXTERNAL_WIDGET */
2671 FRAME_X_SHELL_WIDGET (f) = 0;
2673 if (FRAME_X_GEOM_FREE_ME_PLEASE (f))
2675 xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
2676 FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0;
2681 xfree (f->frame_data);
2687 x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
2693 XSETFRAME(frame, frm);
2695 if (EQ (name, Qforeground))
2697 Lisp_Object color = FACE_FOREGROUND (Vdefault_face, frame);
2700 if (!EQ (color, Vthe_null_color_instance))
2702 fgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2703 XtSetArg (al[ac], XtNforeground, (void *) fgc.pixel); ac++;
2706 else if (EQ (name, Qbackground))
2708 Lisp_Object color = FACE_BACKGROUND (Vdefault_face, frame);
2711 if (!EQ (color, Vthe_null_color_instance))
2713 bgc = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color));
2714 XtSetArg (al[ac], XtNbackground, (void *) bgc.pixel); ac++;
2717 /* Really crappy way to force the modeline shadows to be
2718 redrawn. But effective. */
2719 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (frm);
2720 MARK_FRAME_CHANGED (frm);
2722 else if (EQ (name, Qfont))
2724 Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
2726 if (!EQ (font, Vthe_null_font_instance))
2727 XtSetArg (al[ac], XtNfont,
2728 (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
2734 XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
2736 #ifdef HAVE_TOOLBARS
2737 /* Setting the background clears the entire frame area
2738 including the toolbar so we force an immediate redraw of
2740 if (EQ (name, Qbackground))
2741 MAYBE_DEVMETH (XDEVICE (frm->device), redraw_frame_toolbars, (frm));
2742 #endif /* HAVE_TOOLBARS */
2744 /* Set window manager resize increment hints according to
2745 the new character size */
2746 if (EQ (name, Qfont))
2747 EmacsFrameRecomputeCellSize (FRAME_X_TEXT_WIDGET (frm));
2751 /************************************************************************/
2752 /* initialization */
2753 /************************************************************************/
2756 syms_of_frame_x (void)
2758 defsymbol (&Qwindow_id, "window-id");
2759 defsymbol (&Qx_resource_name, "x-resource-name");
2761 DEFSUBR (Fx_window_id);
2763 DEFSUBR (Fcde_start_drag_internal);
2765 #ifdef HAVE_OFFIX_DND
2766 DEFSUBR (Foffix_start_drag_internal);
2771 console_type_create_frame_x (void)
2774 CONSOLE_HAS_METHOD (x, init_frame_1);
2775 CONSOLE_HAS_METHOD (x, init_frame_2);
2776 CONSOLE_HAS_METHOD (x, init_frame_3);
2777 CONSOLE_HAS_METHOD (x, mark_frame);
2778 CONSOLE_HAS_METHOD (x, focus_on_frame);
2779 CONSOLE_HAS_METHOD (x, delete_frame);
2780 CONSOLE_HAS_METHOD (x, get_mouse_position);
2781 CONSOLE_HAS_METHOD (x, set_mouse_position);
2782 CONSOLE_HAS_METHOD (x, raise_frame);
2783 CONSOLE_HAS_METHOD (x, lower_frame);
2784 CONSOLE_HAS_METHOD (x, make_frame_visible);
2785 CONSOLE_HAS_METHOD (x, make_frame_invisible);
2786 CONSOLE_HAS_METHOD (x, iconify_frame);
2787 CONSOLE_HAS_METHOD (x, set_frame_size);
2788 CONSOLE_HAS_METHOD (x, set_frame_position);
2789 CONSOLE_HAS_METHOD (x, frame_property);
2790 CONSOLE_HAS_METHOD (x, internal_frame_property_p);
2791 CONSOLE_HAS_METHOD (x, frame_properties);
2792 CONSOLE_HAS_METHOD (x, set_frame_properties);
2793 CONSOLE_HAS_METHOD (x, set_title_from_bufbyte);
2794 CONSOLE_HAS_METHOD (x, set_icon_name_from_bufbyte);
2795 CONSOLE_HAS_METHOD (x, frame_visible_p);
2796 CONSOLE_HAS_METHOD (x, frame_totally_visible_p);
2797 CONSOLE_HAS_METHOD (x, frame_iconified_p);
2798 CONSOLE_HAS_METHOD (x, set_frame_pointer);
2799 CONSOLE_HAS_METHOD (x, set_frame_icon);
2800 CONSOLE_HAS_METHOD (x, get_frame_parent);
2801 CONSOLE_HAS_METHOD (x, update_frame_external_traits);
2805 vars_of_frame_x (void)
2807 #ifdef EXTERNAL_WIDGET
2808 Fprovide (intern ("external-widget"));
2811 /* this call uses only safe functions from emacs.c */
2812 init_x_prop_symbols ();
2814 DEFVAR_LISP ("default-x-frame-plist", &Vdefault_x_frame_plist /*
2815 Plist of default frame-creation properties for X frames.
2816 These override what is specified in the resource database and in
2817 `default-frame-plist', but are overridden by the arguments to the
2818 particular call to `make-frame'.
2820 Note: In many cases, properties of a frame are available as specifiers
2821 instead of through the frame-properties mechanism.
2823 Here is a list of recognized frame properties, other than those
2824 documented in `set-frame-properties' (they can be queried and
2825 set at any time, except as otherwise noted):
2827 window-id The X window ID corresponding to the
2828 frame. May be set only at startup, and
2829 only if external widget support was
2830 compiled in; doing so causes the frame
2831 to be created as an "external widget"
2832 in another program that uses an existing
2833 window in the program rather than creating
2835 initially-unmapped If non-nil, the frame will not be visible
2836 when it is created. In this case, you
2837 need to call `make-frame-visible' to make
2839 popup If non-nil, it should be a frame, and this
2840 frame will be created as a "popup" frame
2841 whose parent is the given frame. This
2842 will make the window manager treat the
2843 frame as a dialog box, which may entail
2844 doing different things (e.g. not asking
2845 for positioning, and not iconifying
2846 separate from its parent).
2847 inter-line-space Not currently implemented.
2848 toolbar-shadow-thickness Thickness of toolbar shadows.
2849 background-toolbar-color Color of toolbar background.
2850 bottom-toolbar-shadow-color Color of bottom shadows on toolbars.
2851 (*Not* specific to the bottom-toolbar.)
2852 top-toolbar-shadow-color Color of top shadows on toolbars.
2853 (*Not* specific to the top-toolbar.)
2854 internal-border-width Width of internal border around text area.
2855 border-width Width of external border around text area.
2856 top Y position (in pixels) of the upper-left
2857 outermost corner of the frame (i.e. the
2858 upper-left of the window-manager
2860 left X position (in pixels) of the upper-left
2861 outermost corner of the frame (i.e. the
2862 upper-left of the window-manager
2864 border-color Color of external border around text area.
2865 cursor-color Color of text cursor.
2867 See also `default-frame-plist', which specifies properties which apply
2868 to all frames, not just X frames.
2870 Vdefault_x_frame_plist = Qnil;
2872 x_console_methods->device_specific_frame_props = &Vdefault_x_frame_plist;