X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/7452b7bd70f01fb96f13269250bda32507ce0cf1..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/xfns.c diff --git a/src/xfns.c b/src/xfns.c index f4c24cb09a..65edf6ddb9 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1,6 +1,6 @@ /* Functions for the X window system. -Copyright (C) 1989, 1992-2013 Free Software Foundation, Inc. +Copyright (C) 1989, 1992-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -22,12 +22,9 @@ along with GNU Emacs. If not, see . */ #include #include -/* This makes the fields of a Display accessible, in Xlib header files. */ - -#define XLIB_ILLEGAL_ACCESS - #include "lisp.h" #include "xterm.h" +#include "menu.h" #include "frame.h" #include "window.h" #include "character.h" @@ -46,8 +43,6 @@ along with GNU Emacs. If not, see . */ #include "termchar.h" #include "font.h" -#ifdef HAVE_X_WINDOWS - #include #include @@ -59,6 +54,13 @@ along with GNU Emacs. If not, see . */ #include "xsettings.h" +#ifdef HAVE_XRANDR +#include +#endif +#ifdef HAVE_XINERAMA +#include +#endif + #ifdef USE_GTK #include "gtkutil.h" #endif @@ -123,7 +125,6 @@ extern LWLIB_ID widget_id_tick; #define MAXREQUEST(dpy) (XMaxRequestSize (dpy)) -static Lisp_Object Qsuppress_icon; static Lisp_Object Qundefined_color; static Lisp_Object Qcompound_text, Qcancel_timer; Lisp_Object Qfont_param; @@ -150,7 +151,7 @@ check_x_display_info (Lisp_Object object) struct frame *sf = XFRAME (selected_frame); if (FRAME_X_P (sf) && FRAME_LIVE_P (sf)) - dpyinfo = FRAME_X_DISPLAY_INFO (sf); + dpyinfo = FRAME_DISPLAY_INFO (sf); else if (x_display_list != 0) dpyinfo = x_display_list; else @@ -161,7 +162,7 @@ check_x_display_info (Lisp_Object object) struct terminal *t = get_terminal (object, 1); if (t->type != output_x_window) - error ("Terminal %"pI"d is not an X display", XINT (object)); + error ("Terminal %d is not an X display", t->id); dpyinfo = t->display_info.x; } @@ -169,200 +170,19 @@ check_x_display_info (Lisp_Object object) dpyinfo = x_display_info_for_name (object); else { - FRAME_PTR f = decode_window_system_frame (object); - dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct frame *f = decode_window_system_frame (object); + dpyinfo = FRAME_DISPLAY_INFO (f); } return dpyinfo; } - -/* Return the Emacs frame-object corresponding to an X window. - It could be the frame's main window or an icon window. */ - -/* This function can be called during GC, so use GC_xxx type test macros. */ - -struct frame * -x_window_to_frame (struct x_display_info *dpyinfo, int wdesc) -{ - Lisp_Object tail, frame; - struct frame *f; - - if (wdesc == None) - return NULL; - - FOR_EACH_FRAME (tail, frame) - { - f = XFRAME (frame); - if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo) - continue; - if (f->output_data.x->hourglass_window == wdesc) - return f; -#ifdef USE_X_TOOLKIT - if ((f->output_data.x->edit_widget - && XtWindow (f->output_data.x->edit_widget) == wdesc) - /* A tooltip frame? */ - || (!f->output_data.x->edit_widget - && FRAME_X_WINDOW (f) == wdesc) - || f->output_data.x->icon_desc == wdesc) - return f; -#else /* not USE_X_TOOLKIT */ -#ifdef USE_GTK - if (f->output_data.x->edit_widget) - { - GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); - struct x_output *x = f->output_data.x; - if (gwdesc != 0 && gwdesc == x->edit_widget) - return f; - } -#endif /* USE_GTK */ - if (FRAME_X_WINDOW (f) == wdesc - || f->output_data.x->icon_desc == wdesc) - return f; -#endif /* not USE_X_TOOLKIT */ - } - return 0; -} - -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) -/* Like x_window_to_frame but also compares the window with the widget's - windows. */ - -struct frame * -x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc) -{ - Lisp_Object tail, frame; - struct frame *f, *found = NULL; - struct x_output *x; - - if (wdesc == None) - return NULL; - - FOR_EACH_FRAME (tail, frame) - { - if (found) - break; - f = XFRAME (frame); - if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo) - { - /* This frame matches if the window is any of its widgets. */ - x = f->output_data.x; - if (x->hourglass_window == wdesc) - found = f; - else if (x->widget) - { -#ifdef USE_GTK - GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); - if (gwdesc != 0 - && gtk_widget_get_toplevel (gwdesc) == x->widget) - found = f; -#else - if (wdesc == XtWindow (x->widget) - || wdesc == XtWindow (x->column_widget) - || wdesc == XtWindow (x->edit_widget)) - found = f; - /* Match if the window is this frame's menubar. */ - else if (lw_window_is_in_menubar (wdesc, x->menubar_widget)) - found = f; -#endif - } - else if (FRAME_X_WINDOW (f) == wdesc) - /* A tooltip frame. */ - found = f; - } - } - - return found; -} - -/* Likewise, but consider only the menu bar widget. */ - -struct frame * -x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event) -{ - Window wdesc = event->xany.window; - Lisp_Object tail, frame; - struct frame *f; - struct x_output *x; - - if (wdesc == None) - return NULL; - - FOR_EACH_FRAME (tail, frame) - { - f = XFRAME (frame); - if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo) - continue; - x = f->output_data.x; -#ifdef USE_GTK - if (x->menubar_widget && xg_event_is_for_menubar (f, event)) - return f; -#else - /* Match if the window is this frame's menubar. */ - if (x->menubar_widget - && lw_window_is_in_menubar (wdesc, x->menubar_widget)) - return f; -#endif - } - return 0; -} - -/* Return the frame whose principal (outermost) window is WDESC. - If WDESC is some other (smaller) window, we return 0. */ - -struct frame * -x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc) -{ - Lisp_Object tail, frame; - struct frame *f; - struct x_output *x; - - if (wdesc == None) - return NULL; - - FOR_EACH_FRAME (tail, frame) - { - f = XFRAME (frame); - if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo) - continue; - x = f->output_data.x; - - if (x->widget) - { - /* This frame matches if the window is its topmost widget. */ -#ifdef USE_GTK - GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc); - if (gwdesc == x->widget) - return f; -#else - if (wdesc == XtWindow (x->widget)) - return f; -#if 0 /* I don't know why it did this, - but it seems logically wrong, - and it causes trouble for MapNotify events. */ - /* Match if the window is this frame's menubar. */ - if (x->menubar_widget - && wdesc == XtWindow (x->menubar_widget)) - return f; -#endif -#endif - } - else if (FRAME_X_WINDOW (f) == wdesc) - /* Tooltip frame. */ - return f; - } - return 0; -} -#endif /* USE_X_TOOLKIT || USE_GTK */ - - - /* Store the screen positions of frame F into XPTR and YPTR. These are the positions of the containing window manager window, not Emacs's own window. */ void -x_real_positions (FRAME_PTR f, int *xptr, int *yptr) +x_real_positions (struct frame *f, int *xptr, int *yptr) { int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0); int real_x = 0, real_y = 0; @@ -371,7 +191,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr) Atom actual_type; unsigned long actual_size, bytes_remaining; int rc, actual_format; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); long max_len = 400; Display *dpy = FRAME_X_DISPLAY (f); unsigned char *tmp_data = NULL; @@ -434,7 +254,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr) XTranslateCoordinates (FRAME_X_DISPLAY (f), /* From-window, to-window. */ - FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_DISPLAY_INFO (f)->root_window, FRAME_X_WINDOW (f), /* From-position, to-position. */ @@ -453,7 +273,7 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr) XTranslateCoordinates (FRAME_X_DISPLAY (f), /* From-window, to-window. */ - FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_DISPLAY_INFO (f)->root_window, FRAME_OUTER_WINDOW (f), /* From-position, to-position. */ @@ -509,8 +329,43 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr) *yptr = real_y; } - +/* Get the mouse position in frame relative coordinates. */ + +void +x_relative_mouse_position (struct frame *f, int *x, int *y) +{ + Window root, dummy_window; + int dummy; + + eassert (FRAME_X_P (f)); + + block_input (); + XQueryPointer (FRAME_X_DISPLAY (f), + DefaultRootWindow (FRAME_X_DISPLAY (f)), + + /* The root window which contains the pointer. */ + &root, + + /* Window pointer is on, not used */ + &dummy_window, + + /* The position on that root window. */ + x, y, + + /* x/y in dummy_window coordinates, not used. */ + &dummy, &dummy, + + /* Modifier keys and pointer buttons, about which + we don't care. */ + (unsigned int *) &dummy); + + unblock_input (); + + /* Translate root window coordinates to window coordinates. */ + *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); + *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); +} /* Gamma-correct COLOR on frame F. */ @@ -558,7 +413,7 @@ x_defined_color (struct frame *f, const char *color_name, Signal an error if color can't be allocated. */ static int -x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color) +x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color) { XColor cdef; @@ -574,7 +429,7 @@ x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color) #endif /* Return MONO_COLOR for monochrome frames. */ - if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1) + if (FRAME_DISPLAY_INFO (f)->n_planes == 1) return mono_color; /* x_defined_color is responsible for coping with failures @@ -619,7 +474,7 @@ x_set_tool_bar_position (struct frame *f, may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */ int -xg_set_icon (FRAME_PTR f, Lisp_Object file) +xg_set_icon (struct frame *f, Lisp_Object file) { int result = 0; Lisp_Object found; @@ -653,7 +508,7 @@ xg_set_icon (FRAME_PTR f, Lisp_Object file) } int -xg_set_icon_from_xpm_data (FRAME_PTR f, const char **data) +xg_set_icon_from_xpm_data (struct frame *f, const char **data) { GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data); @@ -757,42 +612,13 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) } } -static Cursor -make_invisible_cursor (struct frame *f) -{ - Display *dpy = FRAME_X_DISPLAY (f); - static char const no_data[] = { 0 }; - Pixmap pix; - XColor col; - Cursor c = 0; - - x_catch_errors (dpy); - pix = XCreateBitmapFromData (dpy, FRAME_X_DISPLAY_INFO (f)->root_window, - no_data, 1, 1); - if (! x_had_errors_p (dpy) && pix != None) - { - Cursor pixc; - col.pixel = 0; - col.red = col.green = col.blue = 0; - col.flags = DoRed | DoGreen | DoBlue; - pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0); - if (! x_had_errors_p (dpy) && pixc != None) - c = pixc; - XFreePixmap (dpy, pix); - } - - x_uncatch_errors (); - - return c; -} - static void x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { struct x_output *x = f->output_data.x; Display *dpy = FRAME_X_DISPLAY (f); Cursor cursor, nontext_cursor, mode_cursor, hand_cursor; - Cursor hourglass_cursor, horizontal_drag_cursor; + Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor; unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f); @@ -860,7 +686,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (!NILP (Vx_window_horizontal_drag_shape)) { - CHECK_NUMBER (Vx_window_horizontal_drag_shape); + CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape); horizontal_drag_cursor = XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape)); } @@ -868,6 +694,16 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) horizontal_drag_cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow); + if (!NILP (Vx_window_vertical_drag_shape)) + { + CHECK_NUMBER (Vx_window_vertical_drag_shape); + vertical_drag_cursor + = XCreateFontCursor (dpy, XINT (Vx_window_vertical_drag_shape)); + } + else + vertical_drag_cursor + = XCreateFontCursor (dpy, XC_sb_v_double_arrow); + /* Check and report errors with the above calls. */ x_check_errors (dpy, "can't set cursor shape: %s"); x_uncatch_errors (); @@ -886,15 +722,13 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color); XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color); XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color); + XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color); } if (FRAME_X_WINDOW (f) != 0) XDefineCursor (dpy, FRAME_X_WINDOW (f), f->output_data.x->current_cursor = cursor); - if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor == 0) - FRAME_X_DISPLAY_INFO (f)->invisible_cursor = make_invisible_cursor (f); - if (cursor != x->text_cursor && x->text_cursor != 0) XFreeCursor (dpy, x->text_cursor); @@ -925,6 +759,11 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) XFreeCursor (dpy, x->horizontal_drag_cursor); x->horizontal_drag_cursor = horizontal_drag_cursor; + if (vertical_drag_cursor != x->vertical_drag_cursor + && x->vertical_drag_cursor != 0) + XFreeCursor (dpy, x->vertical_drag_cursor); + x->vertical_drag_cursor = vertical_drag_cursor; + XFlush (dpy); unblock_input (); @@ -935,7 +774,7 @@ static void x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { unsigned long fore_pixel, pixel; - int fore_pixel_allocated_p = 0, pixel_allocated_p = 0; + bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0; struct x_output *x = f->output_data.x; if (!NILP (Vx_cursor_fore_pixel)) @@ -1028,7 +867,7 @@ x_set_border_pixel (struct frame *f, int pix) Note: this is done in two routines because of the way X10 works. Note: under X11, this is normally the province of the window manager, - and so emacs' border colors may be overridden. */ + and so emacs's border colors may be overridden. */ static void x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) @@ -1043,14 +882,11 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) static void -x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) +x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { set_frame_cursor_types (f, arg); - - /* Make sure the cursor gets redrawn. */ - cursor_type_changed = 1; } - + static void x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -1142,10 +978,11 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) nlines = 0; /* Make sure we redisplay all windows in this frame. */ - windows_or_buffers_changed++; + windows_or_buffers_changed = 59; #if defined (USE_X_TOOLKIT) || defined (USE_GTK) FRAME_MENU_BAR_LINES (f) = 0; + FRAME_MENU_BAR_HEIGHT (f) = 0; if (nlines) { FRAME_EXTERNAL_MENU_BAR (f) = 1; @@ -1163,7 +1000,10 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } #else /* not USE_X_TOOLKIT && not USE_GTK */ FRAME_MENU_BAR_LINES (f) = nlines; - resize_frame_windows (f, FRAME_LINES (f), 0); + FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); + resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); + if (FRAME_X_WINDOW (f)) + x_clear_under_internal_border (f); /* If the menu bar height gets changed, the internal border below the top margin has to be cleared. Also, if the menu bar gets @@ -1176,13 +1016,13 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) int y; /* height can be zero here. */ - if (height > 0 && width > 0) + if (FRAME_X_WINDOW (f) && height > 0 && width > 0) { y = FRAME_TOP_MARGIN_HEIGHT (f); block_input (); x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - 0, y, width, height, False); + 0, y, width, height); unblock_input (); } @@ -1193,7 +1033,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) block_input (); x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - 0, y, width, height, False); + 0, y, width, height); unblock_input (); } @@ -1201,7 +1041,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix); } #endif /* not USE_X_TOOLKIT && not USE_GTK */ - adjust_glyphs (f); + adjust_frame_glyphs (f); run_window_configuration_change_hook (f); } @@ -1215,8 +1055,11 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { - int delta, nlines, root_height; - Lisp_Object root_window; + int nlines; +#if ! defined (USE_GTK) + int delta, root_height; + int unit = FRAME_LINE_HEIGHT (f); +#endif /* Treat tool bars like menu bars. */ if (FRAME_MINIBUF_ONLY_P (f)) @@ -1229,7 +1072,9 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) nlines = 0; #ifdef USE_GTK + FRAME_TOOL_BAR_LINES (f) = 0; + FRAME_TOOL_BAR_HEIGHT (f) = 0; if (nlines) { FRAME_EXTERNAL_TOOL_BAR (f) = 1; @@ -1245,26 +1090,38 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) FRAME_EXTERNAL_TOOL_BAR (f) = 0; } - return; -#endif +#else /* !USE_GTK */ - /* Make sure we redisplay all windows in this frame. */ - ++windows_or_buffers_changed; + /* Make sure we redisplay all windows in this frame. */ + windows_or_buffers_changed = 60; - delta = nlines - FRAME_TOOL_BAR_LINES (f); + /* DELTA is in pixels now. */ + delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit; - /* Don't resize the tool-bar to more than we have room for. */ - root_window = FRAME_ROOT_WINDOW (f); - root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window)); - if (root_height - delta < 1) + /* Don't resize the tool-bar to more than we have room for. Note: The + calculations below and the subsequent call to resize_frame_windows + are inherently flawed because they can make the toolbar higher than + the containing frame. */ + if (delta > 0) { - delta = root_height - 1; - nlines = FRAME_TOOL_BAR_LINES (f) + delta; + root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f))); + if (root_height - delta < unit) + { + delta = root_height - unit; + /* When creating a new frame and toolbar mode is enabled, we + need at least one toolbar line. */ + nlines = max (FRAME_TOOL_BAR_LINES (f) + delta / unit, 1); + } } FRAME_TOOL_BAR_LINES (f) = nlines; - resize_frame_windows (f, FRAME_LINES (f), 0); - adjust_glyphs (f); + FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); + resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); +#if !defined USE_X_TOOLKIT && !defined USE_GTK + if (FRAME_X_WINDOW (f)) + x_clear_under_internal_border (f); +#endif + adjust_frame_glyphs (f); /* We also have to make sure that the internal border at the top of the frame, below the menu bar or tool bar, is redrawn when the @@ -1272,7 +1129,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) below the tool bar if one is displayed, but is below the menu bar if there isn't a tool bar. The tool bar draws into the area below the menu bar. */ - if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0) + if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0) { clear_frame (f); clear_current_matrices (f); @@ -1285,14 +1142,14 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int height = FRAME_INTERNAL_BORDER_WIDTH (f); int width = FRAME_PIXEL_WIDTH (f); - int y = (FRAME_MENU_BAR_LINES (f) + nlines) * FRAME_LINE_HEIGHT (f); + int y = nlines * unit; /* height can be zero here. */ if (height > 0 && width > 0) { block_input (); - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - 0, y, width, height, False); + x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + 0, y, width, height); unblock_input (); } @@ -1300,8 +1157,8 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); } - run_window_configuration_change_hook (f); - + run_window_configuration_change_hook (f); +#endif /* USE_GTK */ } @@ -1426,7 +1283,7 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK); /* We suppress producing escape sequences for composition. */ coding.common_flags &= ~CODING_ANNOTATION_MASK; - coding.destination = xnmalloc (SCHARS (string), 2); + coding.destination = xnmalloc_atomic (SCHARS (string), 2); coding.dst_bytes = SCHARS (string) * 2; encode_coding_object (&coding, string, 0, 0, SCHARS (string), SBYTES (string), Qnil); @@ -1442,7 +1299,7 @@ x_encode_text (Lisp_Object string, Lisp_Object coding_system, int selectionp, icon name to NAME. */ static void -x_set_name_internal (FRAME_PTR f, Lisp_Object name) +x_set_name_internal (struct frame *f, Lisp_Object name) { if (FRAME_X_WINDOW (f)) { @@ -1486,7 +1343,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp, &do_free_text_value); text.encoding = (stringp ? XA_STRING - : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); + : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); text.format = 8; text.nitems = bytes; if (text.nitems != bytes) @@ -1503,7 +1360,7 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) icon.value = x_encode_text (f->icon_name, coding_system, 0, &bytes, &stringp, &do_free_icon_value); icon.encoding = (stringp ? XA_STRING - : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); + : FRAME_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT); icon.format = 8; icon.nitems = bytes; if (icon.nitems != bytes) @@ -1518,8 +1375,8 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) #else /* not USE_GTK */ XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text); XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - FRAME_X_DISPLAY_INFO (f)->Xatom_net_wm_name, - FRAME_X_DISPLAY_INFO (f)->Xatom_UTF8_STRING, + FRAME_DISPLAY_INFO (f)->Xatom_net_wm_name, + FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING, 8, PropModeReplace, SDATA (encoded_name), SBYTES (encoded_name)); @@ -1527,8 +1384,8 @@ x_set_name_internal (FRAME_PTR f, Lisp_Object name) XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon); XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - FRAME_X_DISPLAY_INFO (f)->Xatom_net_wm_icon_name, - FRAME_X_DISPLAY_INFO (f)->Xatom_UTF8_STRING, + FRAME_DISPLAY_INFO (f)->Xatom_net_wm_icon_name, + FRAME_DISPLAY_INFO (f)->Xatom_UTF8_STRING, 8, PropModeReplace, SDATA (encoded_icon_name), SBYTES (encoded_icon_name)); @@ -1563,7 +1420,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit) /* If we're switching from explicit to implicit, we had better update the mode lines and thereby update the title. */ if (f->explicit_name && NILP (name)) - update_mode_lines = 1; + update_mode_lines = 37; f->explicit_name = ! NILP (name); } @@ -1575,10 +1432,10 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit) { /* Check for no change needed in this very common case before we do any consing. */ - if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name, + if (!strcmp (FRAME_DISPLAY_INFO (f)->x_id_name, SSDATA (f->name))) return; - name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name); + name = build_string (FRAME_DISPLAY_INFO (f)->x_id_name); } else CHECK_STRING (name); @@ -1601,7 +1458,7 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit) specified a name for the frame; the name will override any set by the redisplay code. */ static void -x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) +x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { x_set_name (f, arg, 1); } @@ -1610,7 +1467,7 @@ x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) name; names set this way will never override names set by the user's lisp code. */ void -x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) +x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { x_set_name (f, arg, 0); } @@ -1625,7 +1482,7 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) if (EQ (name, f->title)) return; - update_mode_lines = 1; + update_mode_lines = 38; fset_title (f, name); @@ -1640,7 +1497,7 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) void x_set_scroll_bar_default_width (struct frame *f) { - int wid = FRAME_COLUMN_WIDTH (f); + int unit = FRAME_COLUMN_WIDTH (f); #ifdef USE_TOOLKIT_SCROLL_BARS #ifdef USE_GTK int minw = xg_get_default_scrollbar_width (); @@ -1648,17 +1505,14 @@ x_set_scroll_bar_default_width (struct frame *f) int minw = 16; #endif /* A minimum width of 14 doesn't look good for toolkit scroll bars. */ - int width = minw + 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM; - FRAME_CONFIG_SCROLL_BAR_COLS (f) = (width + wid - 1) / wid; - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = width; + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit; + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw; #else - /* Make the actual width at least 14 pixels and a multiple of a - character width. */ - FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; - - /* Use all of that space (aside from required margins) for the - scroll bar. */ - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0; + /* The width of a non-toolkit scrollbar is at least 14 pixels and a + multiple of the frame's character width. */ + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit; + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit; #endif } @@ -1674,7 +1528,7 @@ x_default_scroll_bar_color_parameter (struct frame *f, const char *xprop, const char *xclass, int foreground_p) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Lisp_Object tem; tem = x_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING); @@ -1708,7 +1562,7 @@ x_default_scroll_bar_color_parameter (struct frame *f, #endif /* not USE_TOOLKIT_SCROLL_BARS */ } - x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil)); + x_set_frame_parameters (f, list1 (Fcons (prop, tem))); return tem; } @@ -1723,7 +1577,7 @@ x_default_scroll_bar_color_parameter (struct frame *f, for example, but Xt doesn't). */ static void -hack_wm_protocols (FRAME_PTR f, Widget widget) +hack_wm_protocols (struct frame *f, Widget widget) { Display *dpy = XtDisplay (widget); Window w = XtWindow (widget); @@ -1740,7 +1594,7 @@ hack_wm_protocols (FRAME_PTR f, Widget widget) unsigned long bytes_after; if ((XGetWindowProperty (dpy, w, - FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols, + FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols, (long)0, (long)100, False, XA_ATOM, &type, &format, &nitems, &bytes_after, &catoms) @@ -1752,13 +1606,13 @@ hack_wm_protocols (FRAME_PTR f, Widget widget) { nitems--; if (atoms[nitems] - == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window) + == FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window) need_delete = 0; else if (atoms[nitems] - == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus) + == FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus) need_focus = 0; else if (atoms[nitems] - == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself) + == FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself) need_save = 0; } } @@ -1769,13 +1623,13 @@ hack_wm_protocols (FRAME_PTR f, Widget widget) Atom props [10]; int count = 0; if (need_delete) - props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window; + props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window; if (need_focus) - props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus; + props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_take_focus; if (need_save) - props[count++] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself; + props[count++] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself; if (count) - XChangeProperty (dpy, w, FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols, + XChangeProperty (dpy, w, FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols, XA_ATOM, 32, PropModeAppend, (unsigned char *) props, count); } @@ -1790,12 +1644,12 @@ hack_wm_protocols (FRAME_PTR f, Widget widget) #ifdef HAVE_X_I18N static XFontSet xic_create_xfontset (struct frame *); -static XIMStyle best_xim_style (XIMStyles *, XIMStyles *); +static XIMStyle best_xim_style (XIMStyles *); /* Supported XIM styles, ordered by preference. */ -static XIMStyle supported_xim_styles[] = +static const XIMStyle supported_xim_styles[] = { XIMPreeditPosition | XIMStatusArea, XIMPreeditPosition | XIMStatusNothing, @@ -1827,7 +1681,7 @@ xic_create_fontsetname (const char *base_fontname, int motif) if (xic_default_fontset == base_fontname) { /* There is no base font name, use the default. */ - fontsetname = xmalloc (strlen (base_fontname) + 2); + fontsetname = xmalloc_atomic (strlen (base_fontname) + 2); strcpy (fontsetname, base_fontname); } else @@ -1847,8 +1701,8 @@ xic_create_fontsetname (const char *base_fontname, int motif) /* As the font name doesn't conform to XLFD, we can't modify it to generalize it to allcs and allfamilies. Use the specified font plus the default. */ - fontsetname = xmalloc (strlen (base_fontname) - + strlen (xic_default_fontset) + 3); + fontsetname = xmalloc_atomic (strlen (base_fontname) + + strlen (xic_default_fontset) + 3); strcpy (fontsetname, base_fontname); strcat (fontsetname, sep); strcat (fontsetname, xic_default_fontset); @@ -1920,7 +1774,7 @@ xic_create_fontsetname (const char *base_fontname, int motif) /* Build the actual font set name. */ len = strlen (base_fontname) + strlen (font_allcs) + strlen (font_allfamilies) + strlen (font_all) + 5; - fontsetname = xmalloc (len); + fontsetname = xmalloc_atomic (len); strcpy (fontsetname, base_fontname); strcat (fontsetname, sep); strcat (fontsetname, font_allcs); @@ -1931,7 +1785,7 @@ xic_create_fontsetname (const char *base_fontname, int motif) } } if (motif) - strcat (fontsetname, ":"); + return strcat (fontsetname, ":"); return fontsetname; } #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */ @@ -1970,7 +1824,7 @@ xic_create_xfontset (struct frame *f) struct frame *cf = XFRAME (frame); if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf) - && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f) && FRAME_FONT (f) && FRAME_FONT (f)->pixel_size == pixel_size) { @@ -2059,7 +1913,7 @@ void xic_free_xfontset (struct frame *f) { Lisp_Object rest, frame; - int shared_p = 0; + bool shared_p = 0; if (!FRAME_XIC_FONTSET (f)) return; @@ -2069,7 +1923,7 @@ xic_free_xfontset (struct frame *f) { struct frame *cf = XFRAME (frame); if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf) - && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f) + && FRAME_DISPLAY_INFO (cf) == FRAME_DISPLAY_INFO (f) && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f)) { shared_p = 1; @@ -2081,9 +1935,6 @@ xic_free_xfontset (struct frame *f) /* The fontset is not used anymore. It is safe to free it. */ XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f)); - if (FRAME_XIC_BASE_FONTNAME (f)) - xfree (FRAME_XIC_BASE_FONTNAME (f)); - FRAME_XIC_BASE_FONTNAME (f) = NULL; FRAME_XIC_FONTSET (f) = NULL; } @@ -2093,14 +1944,15 @@ xic_free_xfontset (struct frame *f) input method XIM. */ static XIMStyle -best_xim_style (XIMStyles *user, XIMStyles *xim) +best_xim_style (XIMStyles *xim) { int i, j; + int nr_supported = ARRAYELTS (supported_xim_styles); - for (i = 0; i < user->count_styles; ++i) + for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) - if (user->supported_styles[i] == xim->supported_styles[j]) - return user->supported_styles[i]; + if (supported_xim_styles[i] == xim->supported_styles[j]) + return supported_xim_styles[i]; /* Return the default style. */ return XIMPreeditNothing | XIMStatusNothing; @@ -2108,42 +1960,41 @@ best_xim_style (XIMStyles *user, XIMStyles *xim) /* Create XIC for frame F. */ -static XIMStyle xic_style; - void create_frame_xic (struct frame *f) { XIM xim; XIC xic = NULL; XFontSet xfs = NULL; + XVaNestedList status_attr = NULL; + XVaNestedList preedit_attr = NULL; + XRectangle s_area; + XPoint spot; + XIMStyle xic_style; if (FRAME_XIC (f)) - return; + goto out; - /* Create X fontset. */ - xfs = xic_create_xfontset (f); xim = FRAME_X_XIM (f); - if (xim) - { - XRectangle s_area; - XPoint spot; - XVaNestedList preedit_attr; - XVaNestedList status_attr; + if (!xim) + goto out; - s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1; - spot.x = 0; spot.y = 1; + /* Determine XIC style. */ + xic_style = best_xim_style (FRAME_X_XIM_STYLES (f)); - /* Determine XIC style. */ - if (xic_style == 0) - { - XIMStyles supported_list; - supported_list.count_styles = (sizeof supported_xim_styles - / sizeof supported_xim_styles[0]); - supported_list.supported_styles = supported_xim_styles; - xic_style = best_xim_style (&supported_list, - FRAME_X_XIM_STYLES (f)); - } + /* Create X fontset. */ + if (xic_style & (XIMPreeditPosition | XIMStatusArea)) + { + xfs = xic_create_xfontset (f); + if (!xfs) + goto out; + + FRAME_XIC_FONTSET (f) = xfs; + } + if (xic_style & XIMPreeditPosition) + { + spot.x = 0; spot.y = 1; preedit_attr = XVaCreateNestedList (0, XNFontSet, xfs, XNForeground, @@ -2155,31 +2006,75 @@ create_frame_xic (struct frame *f) : NULL), &spot, NULL); + + if (!preedit_attr) + goto out; + } + + if (xic_style & XIMStatusArea) + { + s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1; status_attr = XVaCreateNestedList (0, - XNArea, - &s_area, - XNFontSet, - xfs, - XNForeground, - FRAME_FOREGROUND_PIXEL (f), - XNBackground, - FRAME_BACKGROUND_PIXEL (f), - NULL); - - xic = XCreateIC (xim, - XNInputStyle, xic_style, - XNClientWindow, FRAME_X_WINDOW (f), - XNFocusWindow, FRAME_X_WINDOW (f), - XNStatusAttributes, status_attr, - XNPreeditAttributes, preedit_attr, - NULL); - XFree (preedit_attr); - XFree (status_attr); + XNArea, + &s_area, + XNFontSet, + xfs, + XNForeground, + FRAME_FOREGROUND_PIXEL (f), + XNBackground, + FRAME_BACKGROUND_PIXEL (f), + NULL); + + if (!status_attr) + goto out; } + if (preedit_attr && status_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNStatusAttributes, status_attr, + XNPreeditAttributes, preedit_attr, + NULL); + else if (preedit_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNPreeditAttributes, preedit_attr, + NULL); + else if (status_attr) + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + XNStatusAttributes, status_attr, + NULL); + else + xic = XCreateIC (xim, + XNInputStyle, xic_style, + XNClientWindow, FRAME_X_WINDOW (f), + XNFocusWindow, FRAME_X_WINDOW (f), + NULL); + + if (!xic) + goto out; + FRAME_XIC (f) = xic; FRAME_XIC_STYLE (f) = xic_style; - FRAME_XIC_FONTSET (f) = xfs; + xfs = NULL; /* Don't free below. */ + + out: + + if (xfs) + free_frame_xic (f); + + if (preedit_attr) + XFree (preedit_attr); + + if (status_attr) + XFree (status_attr); } @@ -2309,12 +2204,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) for the window manager, so GC relocation won't bother it. Elsewhere we specify the window name for the window manager. */ - - { - char *str = SSDATA (Vx_resource_name); - f->namebuf = xmalloc (strlen (str) + 1); - strcpy (f->namebuf, str); - } + f->namebuf = xstrdup (SSDATA (Vx_resource_name)); ac = 0; XtSetArg (al[ac], XtNallowShellResize, 1); ac++; @@ -2322,7 +2212,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++; XtSetArg (al[ac], XtNborderWidth, f->border_width); ac++; XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++; - XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++; + XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS, applicationShellWidgetClass, @@ -2332,16 +2222,12 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) /* maybe_set_screen_title_format (shell_widget); */ pane_widget = lw_create_widget ("main", "pane", widget_id_tick++, - (widget_value *) NULL, - shell_widget, False, - (lw_callback) NULL, - (lw_callback) NULL, - (lw_callback) NULL, - (lw_callback) NULL); + NULL, shell_widget, False, + NULL, NULL, NULL, NULL); ac = 0; XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++; - XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++; + XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; XtSetArg (al[ac], XtNborderWidth, 0); ac++; XtSetValues (pane_widget, al, ac); @@ -2357,7 +2243,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++; XtSetArg (al[ac], XtNemacsFrame, f); ac++; XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++; - XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++; + XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; XtSetArg (al[ac], XtNborderWidth, 0); ac++; frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget, @@ -2483,9 +2369,8 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) be initialized to something relevant to the time we created the window. */ XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget), - FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols, - XA_ATOM, 32, PropModeAppend, - (unsigned char*) NULL, 0); + FRAME_DISPLAY_INFO (f)->Xatom_wm_protocols, + XA_ATOM, 32, PropModeAppend, NULL, 0); /* Make all the standard events reach the Emacs frame. */ attributes.event_mask = STANDARD_EVENT_SET; @@ -2534,7 +2419,7 @@ x_window (struct frame *f, long window_prompting, int minibuffer_only) #else /* not USE_X_TOOLKIT */ #ifdef USE_GTK static void -x_window (FRAME_PTR f) +x_window (struct frame *f) { if (! xg_create_frame_widgets (f)) error ("Unable to create window"); @@ -2644,8 +2529,8 @@ x_window (struct frame *f) /* Request "save yourself" and "delete window" commands from wm. */ { Atom protocols[2]; - protocols[0] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window; - protocols[1] = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself; + protocols[0] = FRAME_DISPLAY_INFO (f)->Xatom_wm_delete_window; + protocols[1] = FRAME_DISPLAY_INFO (f)->Xatom_wm_save_yourself; XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2); } @@ -2705,7 +2590,7 @@ x_icon (struct frame *f, Lisp_Object parms) { Lisp_Object icon_x, icon_y; #if 0 - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); #endif /* Set the position of the icon. Note that twm groups all @@ -2784,16 +2669,12 @@ x_make_gc (struct frame *f) | GCFillStyle | GCLineWidth), &gc_values); - /* Reliefs. */ - f->output_data.x->white_relief.gc = 0; - f->output_data.x->black_relief.gc = 0; - /* 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. */ f->output_data.x->border_tile = (XCreatePixmapFromBitmapData - (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window, + (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, gray_bits, gray_width, gray_height, FRAME_FOREGROUND_PIXEL (f), FRAME_BACKGROUND_PIXEL (f), @@ -2859,7 +2740,7 @@ unwind_create_frame (Lisp_Object frame) if (NILP (Fmemq (frame, Vframe_list))) { #if defined GLYPH_DEBUG && defined ENABLE_CHECKING - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); #endif x_free_frame_resources (f); @@ -2876,17 +2757,22 @@ unwind_create_frame (Lisp_Object frame) return Qnil; } -static Lisp_Object +static void +do_unwind_create_frame (Lisp_Object frame) +{ + unwind_create_frame (frame); +} + +static void unwind_create_frame_1 (Lisp_Object val) { inhibit_lisp_code = val; - return Qnil; } static void x_default_font_parameter (struct frame *f, Lisp_Object parms) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font = Qnil; @@ -2941,7 +2827,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) { /* Remember the explicit font parameter, so we can re-apply it after we've applied the `default' face settings. */ - x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil)); + x_set_frame_parameters (f, list1 (Fcons (Qfont_param, font_param))); } /* This call will make X resources override any system font setting. */ @@ -3000,7 +2886,7 @@ This function is an internal primitive--use `make-frame' instead. */) int minibuffer_only = 0; long window_prompting = 0; int width, height; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; Lisp_Object display; struct x_display_info *dpyinfo = NULL; @@ -3073,6 +2959,8 @@ This function is an internal primitive--use `make-frame' instead. */) f->output_data.x->scroll_bar_top_shadow_pixel = -1; f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; #endif /* USE_TOOLKIT_SCROLL_BARS */ + f->output_data.x->white_relief.pixel = -1; + f->output_data.x->black_relief.pixel = -1; fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", @@ -3080,10 +2968,10 @@ This function is an internal primitive--use `make-frame' instead. */) if (! STRINGP (f->icon_name)) fset_icon_name (f, Qnil); - FRAME_X_DISPLAY_INFO (f) = dpyinfo; + FRAME_DISPLAY_INFO (f) = dpyinfo; - /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */ - record_unwind_protect (unwind_create_frame, frame); + /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ + record_unwind_protect (do_unwind_create_frame, frame); /* These colors will be set anyway later, but it's important to get the color reference counts right, so initialize them! */ @@ -3127,7 +3015,7 @@ This function is an internal primitive--use `make-frame' instead. */) } else { - f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; + f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.x->explicit_parent = 0; } @@ -3193,6 +3081,10 @@ This function is an internal primitive--use `make-frame' instead. */) #endif "internalBorderWidth", "internalBorderWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qright_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qbottom_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); x_default_parameter (f, parms, Qvertical_scroll_bars, #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS) Qright, @@ -3241,6 +3133,17 @@ This function is an internal primitive--use `make-frame' instead. */) happen. */ init_frame_faces (f); + /* PXW: This is a duplicate from below. We have to do it here since + otherwise x_set_tool_bar_lines will work with the character sizes + installed by init_frame_faces while the frame's pixel size is still + calculated from a character size of 1 and we subsequently hit the + eassert (height >= 0) assertion in window_box_height. The + non-pixelwise code apparently worked around this because it had one + frame line vs one toolbar line which left us with a zero root + window height which was obviously wrong as well ... */ + change_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1, 0, 0, 1); + /* Set the menu-bar-lines and tool-bar-lines parameters. We don't look up the X resources controlling the menu-bar and tool-bar here; they are processed specially at startup, and reflected in @@ -3250,7 +3153,7 @@ This function is an internal primitive--use `make-frame' instead. */) could get an infloop in next_frame since the frame is not yet in Vframe_list. */ { - ptrdiff_t count2 = SPECPDL_INDEX (); + dynwind_begin (); record_unwind_protect (unwind_create_frame_1, inhibit_lisp_code); inhibit_lisp_code = Qt; @@ -3263,7 +3166,7 @@ This function is an internal primitive--use `make-frame' instead. */) ? make_number (0) : make_number (1), NULL, NULL, RES_TYPE_NUMBER); - unbind_to (count2, Qnil); + dynwind_end (); } x_default_parameter (f, parms, Qbuffer_predicate, Qnil, @@ -3298,7 +3201,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* Now consider the frame official. */ f->terminal->reference_count++; - FRAME_X_DISPLAY_INFO (f)->reference_count++; + FRAME_DISPLAY_INFO (f)->reference_count++; Vframe_list = Fcons (frame, Vframe_list); /* We need to do this after creating the X window, so that the @@ -3321,12 +3224,11 @@ This function is an internal primitive--use `make-frame' instead. */) /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. Change will not be effected unless different from the current FRAME_LINES (f). */ - width = FRAME_COLS (f); - height = FRAME_LINES (f); - - SET_FRAME_COLS (f, 0); - FRAME_LINES (f) = 0; - change_frame_size (f, height, width, 1, 0, 0); + width = FRAME_TEXT_WIDTH (f); + height = FRAME_TEXT_HEIGHT (f); + FRAME_TEXT_HEIGHT (f) = 0; + SET_FRAME_WIDTH (f, 0); + change_frame_size (f, width, height, 1, 0, 0, 1); #if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Create the menu bar. */ @@ -3412,7 +3314,8 @@ This function is an internal primitive--use `make-frame' instead. */) and similar functions. */ Vwindow_list = Qnil; - return unbind_to (count, frame); + dynwind_end (); + return frame; } @@ -3423,7 +3326,7 @@ This function is an internal primitive--use `make-frame' instead. */) Lisp_Object x_get_focus_frame (struct frame *frame) { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (frame); + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); Lisp_Object xfocus; if (! dpyinfo->x_focus_frame) return Qnil; @@ -3442,12 +3345,9 @@ x_get_focus_frame (struct frame *frame) policy. But I think it's okay to use when it's clearly done following a user-command. */ -DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, - doc: /* Set the input focus to FRAME. -FRAME nil means use the selected frame. */) - (Lisp_Object frame) +void +x_focus_frame (struct frame *f) { - struct frame *f = decode_window_system_frame (frame); Display *dpy = FRAME_X_DISPLAY (f); block_input (); @@ -3469,8 +3369,6 @@ FRAME nil means use the selected frame. */) x_uncatch_errors (); unblock_input (); - - return Qnil; } @@ -3480,7 +3378,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { XColor foo; - FRAME_PTR f = decode_window_system_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_STRING (color); @@ -3495,7 +3393,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { XColor foo; - FRAME_PTR f = decode_window_system_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_STRING (color); @@ -3561,7 +3459,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, doc: /* Return the width in pixels of the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). -If omitted or nil, that stands for the selected frame's display. */) +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel width for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); @@ -3574,7 +3476,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, doc: /* Return the height in pixels of the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). -If omitted or nil, that stands for the selected frame's display. */) +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel height for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); @@ -3682,7 +3588,11 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, doc: /* Return the height in millimeters of the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). -If omitted or nil, that stands for the selected frame's display. */) +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the height in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); @@ -3694,7 +3604,11 @@ DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, doc: /* Return the width in millimeters of the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). -If omitted or nil, that stands for the selected frame's display. */) +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the width in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); @@ -3791,17 +3705,512 @@ If omitted or nil, that stands for the selected frame's display. */) else return Qnil; } - -int -x_pixel_width (register struct frame *f) + +/* Store the geometry of the workarea on display DPYINFO into *RECT. + Return false if and only if the workarea information cannot be + obtained via the _NET_WORKAREA root window property. */ + +#if ! GTK_CHECK_VERSION (3, 4, 0) +static bool +x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect) { - return FRAME_PIXEL_WIDTH (f); + Display *dpy = dpyinfo->display; + long offset, max_len; + Atom target_type, actual_type; + unsigned long actual_size, bytes_remaining; + int rc, actual_format; + unsigned char *tmp_data = NULL; + bool result = false; + + x_catch_errors (dpy); + offset = 0; + max_len = 1; + target_type = XA_CARDINAL; + rc = XGetWindowProperty (dpy, dpyinfo->root_window, + dpyinfo->Xatom_net_current_desktop, + offset, max_len, False, target_type, + &actual_type, &actual_format, &actual_size, + &bytes_remaining, &tmp_data); + if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy) + && actual_format == 32 && actual_size == max_len) + { + long current_desktop = ((long *) tmp_data)[0]; + + XFree (tmp_data); + tmp_data = NULL; + + offset = 4 * current_desktop; + max_len = 4; + rc = XGetWindowProperty (dpy, dpyinfo->root_window, + dpyinfo->Xatom_net_workarea, + offset, max_len, False, target_type, + &actual_type, &actual_format, &actual_size, + &bytes_remaining, &tmp_data); + if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy) + && actual_format == 32 && actual_size == max_len) + { + long *values = (long *) tmp_data; + + rect->x = values[0]; + rect->y = values[1]; + rect->width = values[2]; + rect->height = values[3]; + + XFree (tmp_data); + tmp_data = NULL; + + result = true; + } + } + if (tmp_data) + XFree (tmp_data); + x_uncatch_errors (); + + return result; } +#endif -int -x_pixel_height (register struct frame *f) +#ifndef USE_GTK + +/* Return monitor number where F is "most" or closest to. */ +static int +x_get_monitor_for_frame (struct frame *f, + struct MonitorInfo *monitors, + int n_monitors) +{ + XRectangle frect; + int area = 0, dist = -1; + int best_area = -1, best_dist = -1; + int i; + + if (n_monitors == 1) return 0; + frect.x = f->left_pos; + frect.y = f->top_pos; + frect.width = FRAME_PIXEL_WIDTH (f); + frect.height = FRAME_PIXEL_HEIGHT (f); + + for (i = 0; i < n_monitors; ++i) + { + struct MonitorInfo *mi = &monitors[i]; + XRectangle res; + int a = 0; + + if (mi->geom.width == 0) continue; + + if (x_intersect_rectangles (&mi->geom, &frect, &res)) + { + a = res.width * res.height; + if (a > area) + { + area = a; + best_area = i; + } + } + + if (a == 0 && area == 0) + { + int dx, dy, d; + if (frect.x + frect.width < mi->geom.x) + dx = mi->geom.x - frect.x + frect.width; + else if (frect.x > mi->geom.x + mi->geom.width) + dx = frect.x - mi->geom.x + mi->geom.width; + else + dx = 0; + if (frect.y + frect.height < mi->geom.y) + dy = mi->geom.y - frect.y + frect.height; + else if (frect.y > mi->geom.y + mi->geom.height) + dy = frect.y - mi->geom.y + mi->geom.height; + else + dy = 0; + + d = dx*dx + dy*dy; + if (dist == -1 || dist > d) + { + dist = d; + best_dist = i; + } + } + } + + return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0); +} + +static Lisp_Object +x_make_monitor_attribute_list (struct MonitorInfo *monitors, + int n_monitors, + int primary_monitor, + struct x_display_info *dpyinfo, + const char *source) { - return FRAME_PIXEL_HEIGHT (f); + Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil); + Lisp_Object frame, rest; + + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo + && !EQ (frame, tip_frame)) + { + int i = x_get_monitor_for_frame (f, monitors, n_monitors); + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); + } + } + + return make_monitor_attribute_list (monitors, n_monitors, primary_monitor, + monitor_frames, source); +} + +static Lisp_Object +x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo) +{ + struct MonitorInfo monitor; + XRectangle workarea_r; + + /* Fallback: treat (possibly) multiple physical monitors as if they + formed a single monitor as a whole. This should provide a + consistent result at least on single monitor environments. */ + monitor.geom.x = monitor.geom.y = 0; + monitor.geom.width = x_display_pixel_width (dpyinfo); + monitor.geom.height = x_display_pixel_height (dpyinfo); + monitor.mm_width = WidthMMOfScreen (dpyinfo->screen); + monitor.mm_height = HeightMMOfScreen (dpyinfo->screen); + monitor.name = xstrdup ("combined screen"); + + if (x_get_net_workarea (dpyinfo, &workarea_r)) + monitor.work = workarea_r; + else + monitor.work = monitor.geom; + return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback"); +} + + +#ifdef HAVE_XINERAMA +static Lisp_Object +x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo) +{ + int n_monitors, i; + Lisp_Object attributes_list = Qnil; + Display *dpy = dpyinfo->display; + XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors); + struct MonitorInfo *monitors; + double mm_width_per_pixel, mm_height_per_pixel; + + if (! info || n_monitors == 0) + { + if (info) + XFree (info); + return attributes_list; + } + + mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen) + / x_display_pixel_width (dpyinfo)); + mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen) + / x_display_pixel_height (dpyinfo)); + monitors = xzalloc (n_monitors * sizeof *monitors); + for (i = 0; i < n_monitors; ++i) + { + struct MonitorInfo *mi = &monitors[i]; + XRectangle workarea_r; + + mi->geom.x = info[i].x_org; + mi->geom.y = info[i].y_org; + mi->geom.width = info[i].width; + mi->geom.height = info[i].height; + mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5; + mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5; + mi->name = 0; + + /* Xinerama usually have primary monitor first, just use that. */ + if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r)) + { + mi->work = workarea_r; + if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work)) + mi->work = mi->geom; + } + else + mi->work = mi->geom; + } + XFree (info); + + attributes_list = x_make_monitor_attribute_list (monitors, + n_monitors, + 0, + dpyinfo, + "Xinerama"); + free_monitors (monitors, n_monitors); + return attributes_list; +} +#endif /* HAVE_XINERAMA */ + + +#ifdef HAVE_XRANDR +static Lisp_Object +x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) +{ + Lisp_Object attributes_list = Qnil; + XRRScreenResources *resources; + Display *dpy = dpyinfo->display; + int i, n_monitors, primary = -1; + RROutput pxid = None; + struct MonitorInfo *monitors; + +#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT + resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window); +#else + resources = XRRGetScreenResources (dpy, dpyinfo->root_window); +#endif + if (! resources || resources->noutput == 0) + { + if (resources) + XRRFreeScreenResources (resources); + return Qnil; + } + n_monitors = resources->noutput; + monitors = xzalloc (n_monitors * sizeof *monitors); + +#ifdef HAVE_XRRGETOUTPUTPRIMARY + pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window); +#endif + + for (i = 0; i < n_monitors; ++i) + { + XRROutputInfo *info = XRRGetOutputInfo (dpy, resources, + resources->outputs[i]); + Connection conn = info ? info->connection : RR_Disconnected; + RRCrtc id = info ? info->crtc : None; + + if (strcmp (info->name, "default") == 0) + { + /* Non XRandr 1.2 driver, does not give useful data. */ + XRRFreeOutputInfo (info); + XRRFreeScreenResources (resources); + free_monitors (monitors, n_monitors); + return Qnil; + } + + if (conn != RR_Disconnected && id != None) + { + XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, id); + struct MonitorInfo *mi = &monitors[i]; + XRectangle workarea_r; + + if (! crtc) + { + XRRFreeOutputInfo (info); + continue; + } + + mi->geom.x = crtc->x; + mi->geom.y = crtc->y; + mi->geom.width = crtc->width; + mi->geom.height = crtc->height; + mi->mm_width = info->mm_width; + mi->mm_height = info->mm_height; + mi->name = xstrdup (info->name); + + if (pxid != None && pxid == resources->outputs[i]) + primary = i; + else if (primary == -1 && strcmp (info->name, "LVDS") == 0) + primary = i; + + if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r)) + { + mi->work= workarea_r; + if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work)) + mi->work = mi->geom; + } + else + mi->work = mi->geom; + + XRRFreeCrtcInfo (crtc); + } + XRRFreeOutputInfo (info); + } + XRRFreeScreenResources (resources); + + attributes_list = x_make_monitor_attribute_list (monitors, + n_monitors, + primary, + dpyinfo, + "XRandr"); + free_monitors (monitors, n_monitors); + return attributes_list; +} +#endif /* HAVE_XRANDR */ + +static Lisp_Object +x_get_monitor_attributes (struct x_display_info *dpyinfo) +{ + Lisp_Object attributes_list = Qnil; + Display *dpy = dpyinfo->display; + + (void) dpy; /* Suppress unused variable warning. */ + +#ifdef HAVE_XRANDR + int xrr_event_base, xrr_error_base; + bool xrr_ok = false; + xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base); + if (xrr_ok) + { + int xrr_major, xrr_minor; + XRRQueryVersion (dpy, &xrr_major, &xrr_minor); + xrr_ok = (xrr_major == 1 && xrr_minor >= 2) || xrr_major > 1; + } + + if (xrr_ok) + attributes_list = x_get_monitor_attributes_xrandr (dpyinfo); +#endif /* HAVE_XRANDR */ + +#ifdef HAVE_XINERAMA + if (NILP (attributes_list)) + { + int xin_event_base, xin_error_base; + bool xin_ok = false; + xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base); + if (xin_ok && XineramaIsActive (dpy)) + attributes_list = x_get_monitor_attributes_xinerama (dpyinfo); + } +#endif /* HAVE_XINERAMA */ + + if (NILP (attributes_list)) + attributes_list = x_get_monitor_attributes_fallback (dpyinfo); + + return attributes_list; +} + +#endif /* !USE_GTK */ + +DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list, + Sx_display_monitor_attributes_list, + 0, 1, 0, + doc: /* Return a list of physical monitor attributes on the X display TERMINAL. + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +In addition to the standard attribute keys listed in +`display-monitor-attributes-list', the following keys are contained in +the attributes: + + source -- String describing the source from which multi-monitor + information is obtained, one of \"Gdk\", \"XRandr\", + \"Xinerama\", or \"fallback\" + +Internal use only, use `display-monitor-attributes-list' instead. */) + (Lisp_Object terminal) +{ + struct x_display_info *dpyinfo = check_x_display_info (terminal); + Lisp_Object attributes_list = Qnil; + +#ifdef USE_GTK + double mm_width_per_pixel, mm_height_per_pixel; + GdkDisplay *gdpy; + GdkScreen *gscreen; + gint primary_monitor = 0, n_monitors, i; + Lisp_Object monitor_frames, rest, frame; + static const char *source = "Gdk"; + struct MonitorInfo *monitors; + + block_input (); + mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen) + / x_display_pixel_width (dpyinfo)); + mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen) + / x_display_pixel_height (dpyinfo)); + gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); + gscreen = gdk_display_get_default_screen (gdpy); +#if GTK_CHECK_VERSION (2, 20, 0) + primary_monitor = gdk_screen_get_primary_monitor (gscreen); +#endif + n_monitors = gdk_screen_get_n_monitors (gscreen); + monitor_frames = Fmake_vector (make_number (n_monitors), Qnil); + monitors = xzalloc (n_monitors * sizeof *monitors); + + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo + && !EQ (frame, tip_frame)) + { + GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + + i = gdk_screen_get_monitor_at_window (gscreen, gwin); + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); + } + } + + for (i = 0; i < n_monitors; ++i) + { + gint width_mm = -1, height_mm = -1; + GdkRectangle rec, work; + struct MonitorInfo *mi = &monitors[i]; + + gdk_screen_get_monitor_geometry (gscreen, i, &rec); + +#if GTK_CHECK_VERSION (2, 14, 0) + width_mm = gdk_screen_get_monitor_width_mm (gscreen, i); + height_mm = gdk_screen_get_monitor_height_mm (gscreen, i); +#endif + if (width_mm < 0) + width_mm = rec.width * mm_width_per_pixel + 0.5; + if (height_mm < 0) + height_mm = rec.height * mm_height_per_pixel + 0.5; + +#if GTK_CHECK_VERSION (3, 4, 0) + gdk_screen_get_monitor_workarea (gscreen, i, &work); +#else + /* Emulate the behavior of GTK+ 3.4. */ + { + XRectangle workarea_r; + + if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r)) + { + work.x = workarea_r.x; + work.y = workarea_r.y; + work.width = workarea_r.width; + work.height = workarea_r.height; + if (! gdk_rectangle_intersect (&rec, &work, &work)) + work = rec; + } + else + work = rec; + } +#endif + + + mi->geom.x = rec.x; + mi->geom.y = rec.y; + mi->geom.width = rec.width; + mi->geom.height = rec.height; + mi->work.x = work.x; + mi->work.y = work.y; + mi->work.width = work.width; + mi->work.height = work.height; + mi->mm_width = width_mm; + mi->mm_height = height_mm; + +#if GTK_CHECK_VERSION (2, 14, 0) + mi->name = gdk_screen_get_monitor_plug_name (gscreen, i); +#endif + } + + attributes_list = make_monitor_attribute_list (monitors, + n_monitors, + primary_monitor, + monitor_frames, + source); + unblock_input (); +#else /* not USE_GTK */ + + block_input (); + attributes_list = x_get_monitor_attributes (dpyinfo); + unblock_input (); + +#endif /* not USE_GTK */ + + return attributes_list; } /************************************************************************ @@ -3929,33 +4338,20 @@ select_visual (struct x_display_info *dpyinfo) static struct x_display_info * x_display_info_for_name (Lisp_Object name) { - Lisp_Object names; struct x_display_info *dpyinfo; CHECK_STRING (name); -#if 0 - if (! EQ (Vinitial_window_system, intern ("x"))) - error ("Not using X Windows"); /* That doesn't stop us anymore. */ -#endif - - for (dpyinfo = x_display_list, names = x_display_name_list; - dpyinfo; - dpyinfo = dpyinfo->next, names = XCDR (names)) - { - Lisp_Object tem; - tem = Fstring_equal (XCAR (XCAR (names)), name); - if (!NILP (tem)) - return dpyinfo; - } + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + return dpyinfo; /* Use this general default value to start with. */ Vx_resource_name = Vinvocation_name; validate_x_resource_name (); - dpyinfo = x_term_init (name, (char *)0, - SSDATA (Vx_resource_name)); + dpyinfo = x_term_init (name, 0, SSDATA (Vx_resource_name)); if (dpyinfo == 0) error ("Cannot connect to X server %s", SDATA (name)); @@ -3983,15 +4379,7 @@ terminate Emacs if we can't open the connection. if (! NILP (xrm_string)) CHECK_STRING (xrm_string); -#if 0 - if (! EQ (Vinitial_window_system, intern ("x"))) - error ("Not using X Windows"); /* That doesn't stop us anymore. */ -#endif - - if (! NILP (xrm_string)) - xrm_option = SSDATA (xrm_string); - else - xrm_option = (char *) 0; + xrm_option = NILP (xrm_string) ? 0 : SSDATA (xrm_string); validate_x_resource_name (); @@ -4039,11 +4427,11 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, doc: /* Return the list of display names that Emacs has connections to. */) (void) { - Lisp_Object tail, result; + Lisp_Object result = Qnil; + struct x_display_info *xdi; - result = Qnil; - for (tail = x_display_name_list; CONSP (tail); tail = XCDR (tail)) - result = Fcons (XCAR (XCAR (tail)), result); + for (xdi = x_display_list; xdi; xdi = xdi->next) + result = Fcons (XCAR (xdi->name_list_element), result); return result; } @@ -4072,7 +4460,7 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display. */ /* Wait for responses to all X commands issued so far for frame F. */ void -x_sync (FRAME_PTR f) +x_sync (struct frame *f) { block_input (); XSync (FRAME_X_DISPLAY (f), False); @@ -4138,7 +4526,7 @@ FRAME. Default is to change on the edit X window. */) This applies even if long is more than 32 bits. The X library converts to 32 bits before sending to the X server. */ elsize = element_format == 32 ? sizeof (long) : element_format >> 3; - data = xnmalloc (nelements, elsize); + data = xnmalloc_atomic (nelements, elsize); x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format); } @@ -4198,75 +4586,43 @@ FRAME nil or omitted means use the selected frame. Value is PROP. */) } -DEFUN ("x-window-property", Fx_window_property, Sx_window_property, - 1, 6, 0, - doc: /* Value is the value of window property PROP on FRAME. -If FRAME is nil or omitted, use the selected frame. - -On X Windows, the following optional arguments are also accepted: -If TYPE is nil or omitted, get the property as a string. -Otherwise TYPE is the name of the atom that denotes the type expected. -If SOURCE is non-nil, get the property on that window instead of from -FRAME. The number 0 denotes the root window. -If DELETE-P is non-nil, delete the property after retrieving it. -If VECTOR-RET-P is non-nil, don't return a string but a vector of values. - -On MS Windows, this function accepts but ignores those optional arguments. - -Value is nil if FRAME hasn't a property with name PROP or if PROP has -no value of TYPE (always string in the MS Windows case). */) - (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, - Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) +static Lisp_Object +x_window_property_intern (struct frame *f, + Window target_window, + Atom prop_atom, + Atom target_type, + Lisp_Object delete_p, + Lisp_Object vector_ret_p, + bool *found) { - struct frame *f = decode_window_system_frame (frame); - Atom prop_atom; - int rc; - Lisp_Object prop_value = Qnil; unsigned char *tmp_data = NULL; + Lisp_Object prop_value = Qnil; Atom actual_type; - Atom target_type = XA_STRING; int actual_format; unsigned long actual_size, bytes_remaining; - Window target_window = FRAME_X_WINDOW (f); + int rc; struct gcpro gcpro1; GCPRO1 (prop_value); - CHECK_STRING (prop); - - if (! NILP (source)) - { - CONS_TO_INTEGER (source, Window, target_window); - if (! target_window) - target_window = FRAME_X_DISPLAY_INFO (f)->root_window; - } - block_input (); - if (STRINGP (type)) - { - if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) - target_type = AnyPropertyType; - else - target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); - } - - prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, prop_atom, 0, 0, False, target_type, &actual_type, &actual_format, &actual_size, &bytes_remaining, &tmp_data); - if (rc == Success) - { - int size = bytes_remaining; + *found = actual_format != 0; + + if (rc == Success && *found) + { XFree (tmp_data); tmp_data = NULL; rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, - prop_atom, 0, bytes_remaining, - ! NILP (delete_p), target_type, - &actual_type, &actual_format, - &actual_size, &bytes_remaining, - &tmp_data); + prop_atom, 0, bytes_remaining, + ! NILP (delete_p), target_type, + &actual_type, &actual_format, + &actual_size, &bytes_remaining, + &tmp_data); if (rc == Success && tmp_data) { /* The man page for XGetWindowProperty says: @@ -4294,7 +4650,7 @@ no value of TYPE (always string in the MS Windows case). */) } if (NILP (vector_ret_p)) - prop_value = make_string ((char *) tmp_data, size); + prop_value = make_string ((char *) tmp_data, actual_size); else prop_value = x_property_data_to_lisp (f, tmp_data, @@ -4306,6 +4662,80 @@ no value of TYPE (always string in the MS Windows case). */) if (tmp_data) XFree (tmp_data); } + UNGCPRO; + return prop_value; +} + +DEFUN ("x-window-property", Fx_window_property, Sx_window_property, + 1, 6, 0, + doc: /* Value is the value of window property PROP on FRAME. +If FRAME is nil or omitted, use the selected frame. + +On X Windows, the following optional arguments are also accepted: +If TYPE is nil or omitted, get the property as a string. +Otherwise TYPE is the name of the atom that denotes the type expected. +If SOURCE is non-nil, get the property on that window instead of from +FRAME. The number 0 denotes the root window. +If DELETE-P is non-nil, delete the property after retrieving it. +If VECTOR-RET-P is non-nil, don't return a string but a vector of values. + +On MS Windows, this function accepts but ignores those optional arguments. + +Value is nil if FRAME hasn't a property with name PROP or if PROP has +no value of TYPE (always string in the MS Windows case). */) + (Lisp_Object prop, Lisp_Object frame, Lisp_Object type, + Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p) +{ + struct frame *f = decode_window_system_frame (frame); + Atom prop_atom; + Lisp_Object prop_value = Qnil; + Atom target_type = XA_STRING; + Window target_window = FRAME_X_WINDOW (f); + struct gcpro gcpro1; + bool found; + + GCPRO1 (prop_value); + CHECK_STRING (prop); + + if (! NILP (source)) + { + CONS_TO_INTEGER (source, Window, target_window); + if (! target_window) + target_window = FRAME_DISPLAY_INFO (f)->root_window; + } + + block_input (); + if (STRINGP (type)) + { + if (strcmp ("AnyPropertyType", SSDATA (type)) == 0) + target_type = AnyPropertyType; + else + target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False); + } + + prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); + prop_value = x_window_property_intern (f, + target_window, + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + if (NILP (prop_value) + && ! found + && NILP (source) + && target_window != FRAME_OUTER_WINDOW (f)) + { + prop_value = x_window_property_intern (f, + FRAME_OUTER_WINDOW (f), + prop_atom, + target_type, + delete_p, + vector_ret_p, + &found); + } + + unblock_input (); UNGCPRO; return prop_value; @@ -4446,7 +4876,7 @@ Window tip_window; static Lisp_Object last_show_tip_args; -static Lisp_Object +static void unwind_create_tip_frame (Lisp_Object frame) { Lisp_Object deleted; @@ -4457,8 +4887,6 @@ unwind_create_tip_frame (Lisp_Object frame) tip_window = None; tip_frame = Qnil; } - - return deleted; } @@ -4480,7 +4908,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object frame; Lisp_Object name; int width, height; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3; int face_change_count_before = face_change_count; Lisp_Object buffer; @@ -4534,9 +4962,12 @@ x_create_tip_frame (struct x_display_info *dpyinfo, f->output_data.x->scroll_bar_top_shadow_pixel = -1; f->output_data.x->scroll_bar_bottom_shadow_pixel = -1; #endif /* USE_TOOLKIT_SCROLL_BARS */ + f->output_data.x->white_relief.pixel = -1; + f->output_data.x->black_relief.pixel = -1; + fset_icon_name (f, Qnil); - FRAME_X_DISPLAY_INFO (f) = dpyinfo; - f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; + FRAME_DISPLAY_INFO (f) = dpyinfo; + f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.x->explicit_parent = 0; /* These colors will be set anyway later, but it's important @@ -4623,6 +5054,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo, x_default_parameter (f, parms, Qinternal_border_width, make_number (1), "internalBorderWidth", "internalBorderWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qright_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qbottom_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); /* Also do the stuff which must be set before the window exists. */ x_default_parameter (f, parms, Qforeground_color, build_string ("black"), @@ -4650,14 +5085,14 @@ x_create_tip_frame (struct x_display_info *dpyinfo, happen. */ init_frame_faces (f); - f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window; + f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; x_figure_window_size (f, parms, 0); { XSetWindowAttributes attrs; unsigned long mask; - Atom type = FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip; + Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip; block_input (); mask = CWBackPixel | CWOverrideRedirect | CWEventMask; @@ -4675,7 +5110,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, tip_window = FRAME_X_WINDOW (f) = XCreateWindow (FRAME_X_DISPLAY (f), - FRAME_X_DISPLAY_INFO (f)->root_window, + FRAME_DISPLAY_INFO (f)->root_window, /* x, y, width, height */ 0, 0, 1, 1, /* Border. */ @@ -4683,7 +5118,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, CopyFromParent, InputOutput, CopyFromParent, mask, &attrs); XChangeProperty (FRAME_X_DISPLAY (f), tip_window, - FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type, + FRAME_DISPLAY_INFO (f)->Xatom_net_window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); unblock_input (); @@ -4705,11 +5140,11 @@ x_create_tip_frame (struct x_display_info *dpyinfo, height = FRAME_LINES (f); SET_FRAME_COLS (f, 0); FRAME_LINES (f) = 0; - change_frame_size (f, height, width, 1, 0, 0); + change_frame_size (f, width, height, 1, 0, 0, 0); /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) - Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); + Fmodify_frame_parameters (frame, list1 (Fcons (Qtooltip, Qt))); /* FIXME - can this be done in a similar way to normal frames? http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00641.html */ @@ -4718,17 +5153,16 @@ x_create_tip_frame (struct x_display_info *dpyinfo, { Lisp_Object disptype; - if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1) + if (FRAME_DISPLAY_INFO (f)->n_planes == 1) disptype = intern ("mono"); - else if (FRAME_X_DISPLAY_INFO (f)->visual->class == GrayScale - || FRAME_X_DISPLAY_INFO (f)->visual->class == StaticGray) + else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale + || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray) disptype = intern ("grayscale"); else disptype = intern ("color"); if (NILP (Fframe_parameter (frame, Qdisplay_type))) - Fmodify_frame_parameters (frame, Fcons (Fcons (Qdisplay_type, disptype), - Qnil)); + Fmodify_frame_parameters (frame, list1 (Fcons (Qdisplay_type, disptype))); } /* Set up faces after all frame parameters are known. This call @@ -4747,8 +5181,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, call2 (Qface_set_after_frame_default, frame, Qnil); if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) - Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg), - Qnil)); + Fmodify_frame_parameters (frame, list1 (Fcons (Qbackground_color, bg))); } f->no_split = 1; @@ -4757,7 +5190,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, /* Now that the frame will be official, it counts as a reference to its display and terminal. */ - FRAME_X_DISPLAY_INFO (f)->reference_count++; + FRAME_DISPLAY_INFO (f)->reference_count++; f->terminal->reference_count++; /* It is now ok to make the frame official even if we get an error @@ -4774,7 +5207,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, face_change_count = face_change_count_before; /* Discard the unwind_protect. */ - return unbind_to (count, frame); + dynwind_end (); + return frame; } @@ -4801,7 +5235,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object if (!INTEGERP (left) || !INTEGERP (top)) { block_input (); - XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window, + XQueryPointer (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, &root, &child, root_x, root_y, &win_x, &win_y, &pmask); unblock_input (); } @@ -4811,7 +5245,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object else if (*root_y + XINT (dy) <= 0) *root_y = 0; /* Can happen for negative dy */ else if (*root_y + XINT (dy) + height - <= x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))) + <= x_display_pixel_height (FRAME_DISPLAY_INFO (f))) /* It fits below the pointer */ *root_y += XINT (dy); else if (height + XINT (dy) <= *root_y) @@ -4826,7 +5260,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object else if (*root_x + XINT (dx) <= 0) *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XINT (dx) + width - <= x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))) + <= x_display_pixel_width (FRAME_DISPLAY_INFO (f))) /* It fits to the right of the pointer. */ *root_x += XINT (dx); else if (width + XINT (dx) <= *root_x) @@ -4872,7 +5306,7 @@ Text larger than the specified size is clipped. */) int i, width, height, seen_reversed_p; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; int old_windows_or_buffers_changed = windows_or_buffers_changed; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); specbind (Qinhibit_redisplay, Qt); @@ -4967,6 +5401,10 @@ Text larger than the specified size is clipped. */) parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); if (NILP (Fassq (Qborder_width, parms))) parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); + if (NILP (Fassq (Qbottom_divider_width, parms))) + parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms); + if (NILP (Fassq (Qright_divider_width, parms))) + parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms); if (NILP (Fassq (Qborder_color, parms))) parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); if (NILP (Fassq (Qbackground_color, parms))) @@ -4975,13 +5413,15 @@ Text larger than the specified size is clipped. */) /* Create a frame for the tooltip, and record it in the global variable tip_frame. */ - frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms, string); + frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string); f = XFRAME (frame); /* Set up the frame's root window. */ w = XWINDOW (FRAME_ROOT_WINDOW (f)); w->left_col = 0; w->top_line = 0; + w->pixel_left = 0; + w->pixel_top = 0; if (CONSP (Vx_max_tooltip_size) && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX) @@ -4996,8 +5436,11 @@ Text larger than the specified size is clipped. */) w->total_lines = 40; } + w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f); + w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f); + FRAME_TOTAL_COLS (f) = w->total_cols; - adjust_glyphs (f); + adjust_frame_glyphs (f); w->pseudo_window_p = 1; /* Display the tooltip text in a temporary buffer. */ @@ -5062,10 +5505,12 @@ Text larger than the specified size is clipped. */) { /* w->total_cols and FRAME_TOTAL_COLS want the width in columns, not in pixels. */ + w->pixel_width = width; width /= WINDOW_FRAME_COLUMN_WIDTH (w); w->total_cols = width; FRAME_TOTAL_COLS (f) = width; - adjust_glyphs (f); + SET_FRAME_WIDTH (f, width); + adjust_frame_glyphs (f); clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); try_window (FRAME_ROOT_WINDOW (f), pos, 0); @@ -5122,7 +5567,8 @@ Text larger than the specified size is clipped. */) intern ("x-hide-tip")); UNGCPRO; - return unbind_to (count, Qnil); + dynwind_end (); + return Qnil; } @@ -5144,7 +5590,7 @@ Value is t if tooltip was open, nil otherwise. */) GCPRO2 (frame, timer); tip_frame = tip_timer = deleted = Qnil; - count = SPECPDL_INDEX (); + dynwind_begin (); specbind (Qinhibit_redisplay, Qt); specbind (Qinhibit_quit, Qt); @@ -5175,7 +5621,7 @@ Value is t if tooltip was open, nil otherwise. */) struct frame *f = SELECTED_FRAME (); w = f->output_data.x->menubar_widget; - if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen) + if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) && w != NULL) { block_input (); @@ -5187,7 +5633,8 @@ Value is t if tooltip was open, nil otherwise. */) } UNGCPRO; - return unbind_to (count, deleted); + dynwind_end (); + return deleted; } @@ -5219,8 +5666,8 @@ DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog, static void file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data) { - int *result = (int *) client_data; - XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data; + int *result = client_data; + XmAnyCallbackStruct *cb = call_data; *result = cb->reason; } @@ -5233,14 +5680,14 @@ file_dialog_cb (Widget widget, XtPointer client_data, XtPointer call_data) static void file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data) { - int *result = (int *) client_data; + int *result = client_data; *result = XmCR_CANCEL; } -static Lisp_Object -clean_up_file_dialog (Lisp_Object arg) +static void +clean_up_file_dialog (void *arg) { - Widget dialog = XSAVE_POINTER (arg, 0); + Widget dialog = arg; /* Clean up. */ block_input (); @@ -5248,8 +5695,6 @@ clean_up_file_dialog (Lisp_Object arg) XtDestroyWidget (dialog); x_menu_set_in_use (0); unblock_input (); - - return Qnil; } @@ -5262,7 +5707,8 @@ or directory must exist. This function is only defined on NS, MS Windows, and X Windows with the Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored. Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) - (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p) + (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, + Lisp_Object mustmatch, Lisp_Object only_dir_p) { int result; struct frame *f = SELECTED_FRAME (); @@ -5272,7 +5718,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) Arg al[10]; int ac = 0; XmString dir_xmstring, pattern_xmstring; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; check_window_system (f); @@ -5364,7 +5810,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) XmStringFree (default_xmstring); } - record_unwind_protect (clean_up_file_dialog, make_save_pointer (dialog)); + record_unwind_protect_ptr (clean_up_file_dialog, dialog); /* Process events until the user presses Cancel or OK. */ x_menu_set_in_use (1); @@ -5411,19 +5857,18 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) decoded_file = DECODE_FILE (file); - return unbind_to (count, decoded_file); + dynwind_end (); + return decoded_file; } #endif /* USE_MOTIF */ #ifdef USE_GTK -static Lisp_Object -clean_up_dialog (Lisp_Object arg) +static void +clean_up_dialog (void) { x_menu_set_in_use (0); - - return Qnil; } DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, @@ -5437,11 +5882,11 @@ Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored. Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p) { - FRAME_PTR f = SELECTED_FRAME (); + struct frame *f = SELECTED_FRAME (); char *fn; Lisp_Object file = Qnil; Lisp_Object decoded_file; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; char *cdef_file; @@ -5457,7 +5902,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); - record_unwind_protect (clean_up_dialog, Qnil); + record_unwind_protect_void (clean_up_dialog); block_input (); @@ -5485,7 +5930,8 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) decoded_file = DECODE_FILE (file); - return unbind_to (count, decoded_file); + dynwind_end (); + return decoded_file; } @@ -5500,19 +5946,19 @@ FRAME is the frame on which to pop up the font chooser. If omitted or nil, it defaults to the selected frame. */) (Lisp_Object frame, Lisp_Object ignored) { - FRAME_PTR f = decode_window_system_frame (frame); + struct frame *f = decode_window_system_frame (frame); Lisp_Object font; Lisp_Object font_param; char *default_name = NULL; struct gcpro gcpro1, gcpro2; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); if (popup_activated ()) error ("Trying to use a menu from within a menu-entry"); /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); - record_unwind_protect (clean_up_dialog, Qnil); + record_unwind_protect_void (clean_up_dialog); block_input (); @@ -5537,7 +5983,8 @@ nil, it defaults to the selected frame. */) if (NILP (font)) Fsignal (Qquit, Qnil); - return unbind_to (count, font); + dynwind_end (); + return font; } #endif /* HAVE_FREETYPE */ @@ -5668,6 +6115,8 @@ frame_parm_handler x_frame_parm_handlers[] = x_set_icon_name, x_set_icon_type, x_set_internal_border_width, + x_set_right_divider_width, + x_set_bottom_divider_width, x_set_menu_bar_lines, x_set_mouse_color, x_explicitly_set_name, @@ -5694,15 +6143,12 @@ frame_parm_handler x_frame_parm_handlers[] = void syms_of_xfns (void) { - /* The section below is built by the lisp expression at the top of the file, - just above where these variables are declared. */ - /*&&& init symbols here &&&*/ - DEFSYM (Qsuppress_icon, "suppress-icon"); +#include "xfns.x" + DEFSYM (Qundefined_color, "undefined-color"); DEFSYM (Qcompound_text, "compound-text"); DEFSYM (Qcancel_timer, "cancel-timer"); DEFSYM (Qfont_param, "font-parameter"); - /* This is the end of symbol initialization. */ Fput (Qundefined_color, Qerror_conditions, listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); @@ -5751,6 +6197,13 @@ This variable takes effect when you create a new frame or when you set the mouse color. */); Vx_window_horizontal_drag_shape = Qnil; + DEFVAR_LISP ("x-window-vertical-drag-cursor", + Vx_window_vertical_drag_shape, + doc: /* Pointer shape to use for indicating a window can be dragged vertically. +This variable takes effect when you create a new frame +or when you set the mouse color. */); + Vx_window_vertical_drag_shape = Qnil; + DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, doc: /* A string indicating the foreground color of the cursor box. */); Vx_cursor_fore_pixel = Qnil; @@ -5810,7 +6263,8 @@ Otherwise use Emacs own tooltip implementation. When using Gtk+ tooltips, the tooltip face is not used. */); x_gtk_use_system_tooltips = 1; - Fprovide (intern_c_string ("x"), Qnil); + /* Tell Emacs about this window system. */ + Fprovide (Qx, Qnil); #ifdef USE_X_TOOLKIT Fprovide (intern_c_string ("x-toolkit"), Qnil); @@ -5842,39 +6296,6 @@ When using Gtk+ tooltips, the tooltip face is not used. */); } #endif /* USE_GTK */ - /* X window properties. */ - defsubr (&Sx_change_window_property); - defsubr (&Sx_delete_window_property); - defsubr (&Sx_window_property); - - defsubr (&Sxw_display_color_p); - defsubr (&Sx_display_grayscale_p); - defsubr (&Sxw_color_defined_p); - defsubr (&Sxw_color_values); - defsubr (&Sx_server_max_request_size); - defsubr (&Sx_server_vendor); - defsubr (&Sx_server_version); - defsubr (&Sx_display_pixel_width); - defsubr (&Sx_display_pixel_height); - defsubr (&Sx_display_mm_width); - defsubr (&Sx_display_mm_height); - defsubr (&Sx_display_screens); - defsubr (&Sx_display_planes); - defsubr (&Sx_display_color_cells); - defsubr (&Sx_display_visual_class); - defsubr (&Sx_display_backing_store); - defsubr (&Sx_display_save_under); - defsubr (&Sx_wm_set_size_hint); - defsubr (&Sx_create_frame); - defsubr (&Sx_open_connection); - defsubr (&Sx_close_connection); - defsubr (&Sx_display_list); - defsubr (&Sx_synchronize); - defsubr (&Sx_focus_frame); - defsubr (&Sx_backspace_delete_keys_p); - - defsubr (&Sx_show_tip); - defsubr (&Sx_hide_tip); tip_timer = Qnil; staticpro (&tip_timer); tip_frame = Qnil; @@ -5882,15 +6303,4 @@ When using Gtk+ tooltips, the tooltip face is not used. */); last_show_tip_args = Qnil; staticpro (&last_show_tip_args); - - defsubr (&Sx_uses_old_gtk_dialog); -#if defined (USE_MOTIF) || defined (USE_GTK) - defsubr (&Sx_file_dialog); -#endif - -#if defined (USE_GTK) && defined (HAVE_FREETYPE) - defsubr (&Sx_select_font); -#endif } - -#endif /* HAVE_X_WINDOWS */