# HG changeset patch # User Richard M. Stallman # Date 759561591 0 # Node ID 5c597b8fbabef04558da1a1a3d101c6452e1e79f # Parent 1c506424bb840c2144fbab8a000dad32c756ad13 Find lwlib.h in ../lwlib. (store_class_hints): Function deleted. (Fx_create_frame): Bind x-resource-name to explicit title. (Qx_resource_name): Declared. (syms_of_xfns): Set up Qx_resource_name. (x_window): Fix error message. (x_any_window_to_frame): New function. (x_window_to_frame, x_window): Handle USE_X_TOOLKIT. (x_set_icon_type, x_set_menu_bar_lines, x_set_name): Likewise. (store_class_hints, hack_wm_protocols): New function. diff -r 1c506424bb84 -r 5c597b8fbabe src/xfns.c --- a/src/xfns.c Wed Jan 26 05:10:53 1994 +0000 +++ b/src/xfns.c Wed Jan 26 05:19:51 1994 +0000 @@ -48,6 +48,34 @@ #include "[.bitmaps]gray.xbm" #endif +#ifdef USE_X_TOOLKIT +#include + +#include +#include + +#ifdef USG +#undef USG /* ####KLUDGE for Solaris 2.2 and up */ +#include +#define USG +#else +#include +#endif + +#include "widget.h" + +#include "../lwlib/lwlib.h" + +/* The one and only application context associated with the connection + to the one and only X display that Emacs uses. */ +XtAppContext Xt_app_con; + +/* The one and only application shell. Emacs screens are popup shells of this + application. */ +Widget Xt_app_shell; + +#endif /* USE_X_TOOLKIT */ + #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) @@ -195,6 +223,7 @@ Lisp_Object Qvisibility; Lisp_Object Qwindow_id; Lisp_Object Qx_frame_parameter; +Lisp_Object Qx_resource_name; /* The below are defined in frame.c. */ extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; @@ -230,13 +259,58 @@ if (XGCTYPE (frame) != Lisp_Frame) continue; f = XFRAME (frame); +#ifdef USE_X_TOOLKIT + if (f->display.nothing == 1) + return 0; + if (f->display.x->edit_widget + && XtWindow (f->display.x->edit_widget) == wdesc + || f->display.x->icon_desc == wdesc) + return f; +#else /* not USE_X_TOOLKIT */ if (FRAME_X_WINDOW (f) == wdesc || f->display.x->icon_desc == wdesc) return f; +#endif /* not USE_X_TOOLKIT */ } return 0; } +#ifdef USE_X_TOOLKIT +/* Like x_window_to_frame but also compares the window with the widget's + windows. */ + +struct frame * +x_any_window_to_frame (wdesc) + int wdesc; +{ + Lisp_Object tail, frame; + struct frame *f; + struct x_display *x; + + for (tail = Vframe_list; XGCTYPE (tail) == Lisp_Cons; + tail = XCONS (tail)->cdr) + { + frame = XCONS (tail)->car; + if (XGCTYPE (frame) != Lisp_Frame) + continue; + f = XFRAME (frame); + if (f->display.nothing == 1) + return 0; + x = f->display.x; + /* This frame matches if the window is any of its widgets. */ + if (wdesc == XtWindow (x->widget) + || wdesc == XtWindow (x->column_widget) + || wdesc == XtWindow (x->edit_widget)) + return f; + /* Match if the window is this frame's menubar. */ + if (x->menubar_widget + && wdesc == XtWindow (x->menubar_widget)) + return f; + } + return 0; +} +#endif /* USE_X_TOOLKIT */ + /* Connect the frame-parameter names for X frames to the ways of passing the parameter values to the window system. @@ -856,6 +930,9 @@ /* If the window was unmapped (and its icon was mapped), the new icon is not mapped, so map the window in its stead. */ if (FRAME_VISIBLE_P (f)) +#ifdef USE_X_TOOLKIT + XtPopup (f->display.x->widget, XtGrabNone); +#endif XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); XFlushQueue (); @@ -993,8 +1070,21 @@ else nlines = 0; +#ifdef USE_X_TOOLKIT + FRAME_MENU_BAR_LINES (f) = 0; + if (nlines) + FRAME_EXTERNAL_MENU_BAR (f) = 1; + else + { + if (FRAME_EXTERNAL_MENU_BAR (f) == 1) + XtDestroyWidget (f->display.x->menubar_widget); + FRAME_EXTERNAL_MENU_BAR (f) = 0; + f->display.x->menubar_widget = 0; + } +#else /* not USE_X_TOOLKIT */ FRAME_MENU_BAR_LINES (f) = nlines; x_set_menu_bar_lines_1 (f->root_window, nlines - olines); +#endif /* not USE_X_TOOLKIT */ } /* Change the name of frame F to NAME. If NAME is nil, set F's name to @@ -1041,7 +1131,6 @@ if (FRAME_X_WINDOW (f)) { BLOCK_INPUT; - #ifdef HAVE_X11R4 { XTextProperty text; @@ -1049,16 +1138,21 @@ text.encoding = XA_STRING; text.format = 8; text.nitems = XSTRING (name)->size; +#ifdef USE_X_TOOLKIT + XSetWMName (x_current_display, XtWindow (f->display.x->widget), &text); + XSetWMIconName (x_current_display, XtWindow (f->display.x->widget), + &text); +#else /* not USE_X_TOOLKIT */ XSetWMName (x_current_display, FRAME_X_WINDOW (f), &text); XSetWMIconName (x_current_display, FRAME_X_WINDOW (f), &text); +#endif /* not USE_X_TOOLKIT */ } -#else +#else /* not HAVE_X11R4 */ XSetIconName (XDISPLAY FRAME_X_WINDOW (f), XSTRING (name)->data); XStoreName (XDISPLAY FRAME_X_WINDOW (f), XSTRING (name)->data); -#endif - +#endif /* not HAVE_X11R4 */ UNBLOCK_INPUT; } @@ -1153,6 +1247,7 @@ register char *value; char *name_key; char *class_key; + Lisp_Object resname; check_x (); @@ -1167,12 +1262,13 @@ error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither"); validate_x_resource_name (); + resname = Vx_resource_name; if (NILP (component)) { /* Allocate space for the components, the dots which separate them, and the final '\0'. */ - name_key = (char *) alloca (XSTRING (Vx_resource_name)->size + name_key = (char *) alloca (XSTRING (resname)->size + XSTRING (attribute)->size + 2); class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1) @@ -1180,7 +1276,7 @@ + 2); sprintf (name_key, "%s.%s", - XSTRING (Vx_resource_name)->data, + XSTRING (resname)->data, XSTRING (attribute)->data); sprintf (class_key, "%s.%s", EMACS_CLASS, @@ -1188,7 +1284,7 @@ } else { - name_key = (char *) alloca (XSTRING (Vx_resource_name)->size + name_key = (char *) alloca (XSTRING (resname)->size + XSTRING (component)->size + XSTRING (attribute)->size + 3); @@ -1199,7 +1295,7 @@ + 3); sprintf (name_key, "%s.%s.%s", - XSTRING (Vx_resource_name)->data, + XSTRING (resname)->data, XSTRING (component)->data, XSTRING (attribute)->data); sprintf (class_key, "%s.%s.%s", @@ -1269,7 +1365,7 @@ } #define Fx_get_resource(attribute, class, component, subclass) \ - Fx_get_default(attribute) + Fx_get_default (attribute) #endif /* X10 */ @@ -1545,15 +1641,143 @@ (unsigned char *) protocols, count); return True; } -#endif /* !HAVE_X11R4 && !HAVE_XSETWMPROTOCOLS */ +#endif /* not HAVE_X11R4 && not HAVE_XSETWMPROTOCOLS */ + +#ifdef USE_X_TOOLKIT + +/* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS + and WM_DELETE_WINDOW, then add them. (They may already be present + because of the toolkit (Motif adds them, for example, but Xt doesn't). */ + +static void +hack_wm_protocols (widget) + Widget widget; +{ + Display *dpy = XtDisplay (widget); + Window w = XtWindow (widget); + int need_delete = 1; + int need_focus = 1; + + BLOCK_INPUT; + { + Atom type, *atoms = 0; + int format = 0; + unsigned long nitems = 0; + unsigned long bytes_after; + + if (Success == XGetWindowProperty (dpy, w, Xatom_wm_protocols, + 0, 100, False, XA_ATOM, + &type, &format, &nitems, &bytes_after, + (unsigned char **) &atoms) + && format == 32 && type == XA_ATOM) + while (nitems > 0) + { + nitems--; + if (atoms [nitems] == Xatom_wm_delete_window) need_delete = 0; + else if (atoms [nitems] == Xatom_wm_take_focus) need_focus = 0; + } + if (atoms) XFree ((char *) atoms); + } + { + Atom props [10]; + int count = 0; + if (need_delete) props [count++] = Xatom_wm_delete_window; + if (need_focus) props [count++] = Xatom_wm_take_focus; + if (count) + XChangeProperty (dpy, w, Xatom_wm_protocols, XA_ATOM, 32, PropModeAppend, + (unsigned char *) props, count); + } + UNBLOCK_INPUT; +} +#endif + +/* Create and set up the X window or widget for frame F. */ static void x_window (f) struct frame *f; { + XClassHint class_hints; + +#ifdef USE_X_TOOLKIT + Widget shell_widget; + Widget pane_widget; + Widget screen_widget; + char* name; + Arg al [25]; + int ac; + + BLOCK_INPUT; + + if (STRINGP (f->name)) + name = (char*) XSTRING (f->name)->data; + else + name = "emacs"; + + ac = 0; + XtSetArg (al[ac], XtNallowShellResize, 1); ac++; + XtSetArg (al[ac], XtNinput, 1); ac++; + XtSetArg (al[ac], XtNx, f->display.x->left_pos); ac++; + XtSetArg (al[ac], XtNy, f->display.x->top_pos); ac++; + shell_widget = XtCreatePopupShell ("shell", + topLevelShellWidgetClass, + Xt_app_shell, al, ac); + + /* maybe_set_screen_title_format (shell_widget); */ + + + ac = 0; + XtSetArg (al[ac], XtNborderWidth, 0); ac++; + pane_widget = XtCreateWidget ("pane", + panedWidgetClass, + shell_widget, al, ac); + + /* mappedWhenManaged to false tells to the paned window to not map/unmap + * the emacs screen when changing menubar. This reduces flickering a lot. + */ + + ac = 0; + XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++; + XtSetArg (al[ac], XtNshowGrip, 0); ac++; + XtSetArg (al[ac], XtNallowResize, 1); ac++; + XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++; + XtSetArg (al[ac], XtNemacsFrame, f); ac++; + screen_widget = XtCreateWidget (name, + emacsFrameClass, + pane_widget, al, ac); + + f->display.x->edit_widget = screen_widget; + f->display.x->widget = shell_widget; + f->display.x->column_widget = pane_widget; + + XtManageChild (screen_widget); + XtManageChild (pane_widget); + XtRealizeWidget (shell_widget); + + FRAME_X_WINDOW (f) = XtWindow (screen_widget); + + validate_x_resource_name (); + class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data; + class_hints.res_class = EMACS_CLASS; + XSetClassHint (x_current_display, XtWindow (shell_widget), &class_hints); + + hack_wm_protocols (shell_widget); + + /* Do a stupid property change to force the server to generate a + propertyNotify event so that the event_stream server timestamp will + be initialized to something relevant to the time we created the window. + */ + XChangeProperty (XtDisplay (screen_widget), XtWindow (screen_widget), + Xatom_wm_protocols, XA_ATOM, 32, PropModeAppend, + (unsigned char*) NULL, 0); + + XtMapWidget (screen_widget); + +#else /* not USE_X_TOOLKIT */ + XSetWindowAttributes attributes; unsigned long attribute_mask; - XClassHint class_hints; + attributes.background_pixel = f->display.x->background_pixel; attributes.border_pixel = f->display.x->border_pixel; @@ -1595,6 +1819,8 @@ XSetWMProtocols (x_current_display, FRAME_X_WINDOW (f), &Xatom_wm_delete_window, 1); +#endif /* not USE_X_TOOLKIT */ + /* x_set_name normally ignores requests to set the name if the requested name is the same as the current name. This is the one place where that assumption isn't correct; f->name is set, but @@ -1610,10 +1836,11 @@ XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->text_cursor); + UNBLOCK_INPUT; if (FRAME_X_WINDOW (f) == 0) - error ("Unable to create window."); + error ("Unable to create window"); } /* Handle the icon stuff for this window. Perhaps later we might @@ -1676,13 +1903,13 @@ BLOCK_INPUT; /* Create the GC's of this frame. - Note that many default values are used. */ + Note that many default values are used. */ /* Normal video */ gc_values.font = f->display.x->font->fid; gc_values.foreground = f->display.x->foreground_pixel; gc_values.background = f->display.x->background_pixel; - gc_values.line_width = 0; /* Means 1 using fast algorithm. */ + gc_values.line_width = 0; /* Means 1 using fast algorithm. */ f->display.x->normal_gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), GCLineWidth | GCFont @@ -1698,7 +1925,7 @@ | GCLineWidth, &gc_values); - /* Cursor has cursor-color background, background-color foreground. */ + /* Cursor has cursor-color background, background-color foreground. */ gc_values.foreground = f->display.x->background_pixel; gc_values.background = f->display.x->cursor_pixel; gc_values.fill_style = FillOpaqueStippled; @@ -1713,7 +1940,7 @@ /* Create the gray border tile used when the pointer is not in the frame. Since this depends on the frame's pixel values, - this must be done on a per-frame basis. */ + this must be done on a per-frame basis. */ f->display.x->border_tile = (XCreatePixmapFromBitmapData (x_current_display, ROOT_WINDOW, @@ -1745,6 +1972,7 @@ int minibuffer_only = 0; long window_prompting = 0; int width, height; + int count = specpdl_ptr - specpdl; check_x (); @@ -1781,6 +2009,8 @@ { f->name = name; f->explicit_name = 1; + /* use the frame's title when getting resources for this frame. */ + specbind (Qx_resource_name, name); } XSET (frame, Lisp_Frame, f); @@ -1820,6 +2050,7 @@ x_default_parameter (f, parms, Qfont, font, "font", "Font", string); } + x_default_parameter (f, parms, Qborder_width, make_number (2), "borderwidth", "BorderWidth", number); /* This defaults to 2 in order to match xterm. We recognize either @@ -1915,7 +2146,7 @@ ; } - return frame; + return unbind_to (count, frame); #else /* X10 */ struct frame *f; Lisp_Object frame, tem; @@ -2755,8 +2986,8 @@ register int font_h = FONT_HEIGHT (f->display.x->font); int y = top_y; int x = line_len (y); - XPoint *pixel_points = (XPoint *) - alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint)); + XPoint *pixel_points + = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint)); register XPoint *this_point = pixel_points; /* Do the horizontal top line/lines */ @@ -3797,6 +4028,8 @@ staticpro (&Qwindow_id); Qx_frame_parameter = intern ("x-frame-parameter"); staticpro (&Qx_frame_parameter); + Qx_resource_name = intern ("x-resource-name"); + staticpro (&Qx_resource_name); /* This is the end of symbol initialization. */ Fput (Qundefined_color, Qerror_conditions,