X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/af80458d7e9d2f81a8d13a0b4ad152743c34520c..21bf394d7d1065a886c486f00c614ca905db1ed5:/src/w32fns.c diff --git a/src/w32fns.c b/src/w32fns.c index 0785e685e6..79011f9afc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -106,6 +106,7 @@ Lisp_Object Qalt; Lisp_Object Qctrl; Lisp_Object Qcontrol; Lisp_Object Qshift; +static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes; /* Prefix for system colors. */ @@ -131,6 +132,15 @@ static HWND track_mouse_window; #ifndef MONITOR_DEFAULT_TO_NEAREST #define MONITOR_DEFAULT_TO_NEAREST 2 #endif +#ifndef MONITORINFOF_PRIMARY +#define MONITORINFOF_PRIMARY 1 +#endif +#ifndef SM_XVIRTUALSCREEN +#define SM_XVIRTUALSCREEN 76 +#endif +#ifndef SM_YVIRTUALSCREEN +#define SM_YVIRTUALSCREEN 77 +#endif /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't. To avoid a compile error on one or the other, redefine with a new name. */ struct MONITOR_INFO @@ -141,6 +151,18 @@ struct MONITOR_INFO DWORD dwFlags; }; +#ifndef CCHDEVICENAME +#define CCHDEVICENAME 32 +#endif +struct MONITOR_INFO_EX +{ + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; + char szDevice[CCHDEVICENAME]; +}; + /* Reportedly, MSVC does not have this in its headers. */ #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500 DECLARE_HANDLE(HMONITOR); @@ -159,6 +181,10 @@ typedef BOOL (WINAPI * GetMonitorInfo_Proc) (IN HMONITOR monitor, OUT struct MONITOR_INFO* info); typedef HMONITOR (WINAPI * MonitorFromWindow_Proc) (IN HWND hwnd, IN DWORD dwFlags); +typedef BOOL CALLBACK (* MonitorEnum_Proc) + (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData); +typedef BOOL (WINAPI * EnumDisplayMonitors_Proc) + (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData); TrackMouseEvent_Proc track_mouse_event_fn = NULL; ImmGetCompositionString_Proc get_composition_string_fn = NULL; @@ -168,6 +194,7 @@ ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL; MonitorFromPoint_Proc monitor_from_point_fn = NULL; GetMonitorInfo_Proc get_monitor_info_fn = NULL; MonitorFromWindow_Proc monitor_from_window_fn = NULL; +EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL; #ifdef NTGUI_UNICODE #define unicode_append_menu AppendMenuW @@ -250,7 +277,7 @@ check_x_display_info (Lisp_Object frame) struct frame *sf = XFRAME (selected_frame); if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf)) - return FRAME_W32_DISPLAY_INFO (sf); + return FRAME_DISPLAY_INFO (sf); else return &one_w32_display_info; } @@ -258,13 +285,13 @@ check_x_display_info (Lisp_Object frame) return x_display_info_for_name (frame); else { - FRAME_PTR f; + struct frame *f; CHECK_LIVE_FRAME (frame); f = XFRAME (frame); if (! FRAME_W32_P (f)) error ("Non-W32 frame used"); - return FRAME_W32_DISPLAY_INFO (f); + return FRAME_DISPLAY_INFO (f); } } @@ -280,7 +307,7 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc) FOR_EACH_FRAME (tail, frame) { f = XFRAME (frame); - if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo) + if (!FRAME_W32_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo) continue; if (FRAME_W32_WINDOW (f) == wdesc) @@ -291,7 +318,7 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc) static Lisp_Object unwind_create_frame (Lisp_Object); -static Lisp_Object unwind_create_tip_frame (Lisp_Object); +static void unwind_create_tip_frame (Lisp_Object); static void my_create_window (struct frame *); static void my_create_tip_window (struct frame *); @@ -317,7 +344,7 @@ void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object); 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) { POINT pt; RECT rect; @@ -992,7 +1019,7 @@ x_to_w32_color (const char * colorname) } void -w32_regenerate_palette (FRAME_PTR f) +w32_regenerate_palette (struct frame *f) { struct w32_palette_entry * list; LOGPALETTE * log_palette; @@ -1000,18 +1027,18 @@ w32_regenerate_palette (FRAME_PTR f) int i; /* don't bother trying to create palette if not supported */ - if (! FRAME_W32_DISPLAY_INFO (f)->has_palette) + if (! FRAME_DISPLAY_INFO (f)->has_palette) return; log_palette = (LOGPALETTE *) alloca (sizeof (LOGPALETTE) + - FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY)); + FRAME_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY)); log_palette->palVersion = 0x300; - log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors; + log_palette->palNumEntries = FRAME_DISPLAY_INFO (f)->num_colors; - list = FRAME_W32_DISPLAY_INFO (f)->color_list; + list = FRAME_DISPLAY_INFO (f)->color_list; for (i = 0; - i < FRAME_W32_DISPLAY_INFO (f)->num_colors; + i < FRAME_DISPLAY_INFO (f)->num_colors; i++, list = list->next) log_palette->palPalEntry[i] = list->entry; @@ -1019,9 +1046,9 @@ w32_regenerate_palette (FRAME_PTR f) enter_crit (); - if (FRAME_W32_DISPLAY_INFO (f)->palette) - DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette); - FRAME_W32_DISPLAY_INFO (f)->palette = new_palette; + if (FRAME_DISPLAY_INFO (f)->palette) + DeleteObject (FRAME_DISPLAY_INFO (f)->palette); + FRAME_DISPLAY_INFO (f)->palette = new_palette; /* Realize display palette and garbage all frames. */ release_frame_dc (f, get_frame_dc (f)); @@ -1042,9 +1069,9 @@ w32_regenerate_palette (FRAME_PTR f) #if 0 /* Keep these around in case we ever want to track color usage. */ void -w32_map_color (FRAME_PTR f, COLORREF color) +w32_map_color (struct frame *f, COLORREF color) { - struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list; + struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list; if (NILP (Vw32_enable_palette)) return; @@ -1064,19 +1091,19 @@ w32_map_color (FRAME_PTR f, COLORREF color) list = xmalloc (sizeof (struct w32_palette_entry)); SET_W32_COLOR (list->entry, color); list->refcount = 1; - list->next = FRAME_W32_DISPLAY_INFO (f)->color_list; - FRAME_W32_DISPLAY_INFO (f)->color_list = list; - FRAME_W32_DISPLAY_INFO (f)->num_colors++; + list->next = FRAME_DISPLAY_INFO (f)->color_list; + FRAME_DISPLAY_INFO (f)->color_list = list; + FRAME_DISPLAY_INFO (f)->num_colors++; /* set flag that palette must be regenerated */ - FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE; + FRAME_DISPLAY_INFO (f)->regen_palette = TRUE; } void -w32_unmap_color (FRAME_PTR f, COLORREF color) +w32_unmap_color (struct frame *f, COLORREF color) { - struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list; - struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list; + struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list; + struct w32_palette_entry **prev = &FRAME_DISPLAY_INFO (f)->color_list; if (NILP (Vw32_enable_palette)) return; @@ -1090,7 +1117,7 @@ w32_unmap_color (FRAME_PTR f, COLORREF color) { *prev = list->next; xfree (list); - FRAME_W32_DISPLAY_INFO (f)->num_colors--; + FRAME_DISPLAY_INFO (f)->num_colors--; break; } else @@ -1101,7 +1128,7 @@ w32_unmap_color (FRAME_PTR f, COLORREF color) } /* set flag that palette must be regenerated */ - FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE; + FRAME_DISPLAY_INFO (f)->regen_palette = TRUE; } #endif @@ -1126,7 +1153,7 @@ gamma_correct (struct frame *f, COLORREF *color) If ALLOC is nonzero, allocate a new colormap cell. */ int -w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc) +w32_defined_color (struct frame *f, const char *color, XColor *color_def, int alloc) { register Lisp_Object tem; COLORREF w32_color_ref; @@ -1197,7 +1224,7 @@ w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc) ARG says. */ int -x_decode_color (FRAME_PTR f, Lisp_Object arg, int def) +x_decode_color (struct frame *f, Lisp_Object arg, int def) { XColor cdef; @@ -1208,7 +1235,7 @@ x_decode_color (FRAME_PTR f, Lisp_Object arg, int def) else if (strcmp (SDATA (arg), "white") == 0) return WHITE_PIX_DEFAULT (f); - if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1) + if ((FRAME_DISPLAY_INFO (f)->n_planes * FRAME_DISPLAY_INFO (f)->n_cbits) == 1) return def; /* w32_defined_color is responsible for coping with failures @@ -1356,6 +1383,17 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) horizontal_drag_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow); + if (!NILP (Vx_window_vertical_drag_shape)) + { + CHECK_NUMBER (Vx_window_vertical_drag_shape); + vertical_drag_cursor + = XCreateFontCursor (FRAME_X_DISPLAY (f), + XINT (Vx_window_vertical_drag_shape)); + } + else + vertical_drag_cursor + = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_v_double_arrow); + /* Check and report errors with the above calls. */ x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s"); x_uncatch_errors (FRAME_W32_DISPLAY (f), count); @@ -1498,14 +1536,11 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) 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; } - + void x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -1599,6 +1634,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) nlines = 0; FRAME_MENU_BAR_LINES (f) = 0; + FRAME_MENU_BAR_HEIGHT (f) = 0; if (nlines) FRAME_EXTERNAL_MENU_BAR (f) = 1; else @@ -1610,24 +1646,25 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) /* Adjust the frame size so that the client (text) dimensions remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being set correctly. */ - x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); + x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); do_pending_window_change (0); } - adjust_glyphs (f); + adjust_frame_glyphs (f); } /* Set the number of lines used for the tool bar of frame F to VALUE. - VALUE not an integer, or < 0 means set the lines to zero. OLDVAL - is the old number of tool bar lines. This function changes the - height of all windows on frame F to match the new tool bar height. - The frame's height doesn't change. */ + VALUE not an integer, or < 0 means set the lines to zero. OLDVAL is + the old number of tool bar lines (and is unused). This function may + change the height of all windows on frame F to match the new tool bar + height. By design, the frame's height doesn't change (but maybe it + should if we don't get enough space otherwise). */ 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 unit = FRAME_LINE_HEIGHT (f); /* Treat tool bars like menu bars. */ if (FRAME_MINIBUF_ONLY_P (f)) @@ -1640,22 +1677,28 @@ x_set_tool_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 = 23; - 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. FIXME: + This must use window_sizable eventually !!!!!!!!!!!! */ + 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; + nlines = (root_height / unit) + min (1, (root_height % unit)); + } } 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); + ++windows_or_buffers_changed; + resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1); + 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 @@ -1663,7 +1706,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_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0) + if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0) { clear_frame (f); clear_current_matrices (f); @@ -1676,7 +1719,7 @@ 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 = nlines * FRAME_LINE_HEIGHT (f); + int y = nlines * unit; block_input (); { @@ -1716,7 +1759,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 = 25; f->explicit_name = ! NILP (name); } @@ -1728,10 +1771,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_W32_DISPLAY_INFO (f)->w32_id_name, + if (!strcmp (FRAME_DISPLAY_INFO (f)->w32_id_name, SDATA (f->name))) return; - name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name); + name = build_string (FRAME_DISPLAY_INFO (f)->w32_id_name); } else CHECK_STRING (name); @@ -1760,7 +1803,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. */ 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); } @@ -1769,7 +1812,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); } @@ -1784,7 +1827,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 = 26; fset_title (f, name); @@ -1866,16 +1909,11 @@ w32_init_class (HINSTANCE hinst) static HWND w32_createscrollbar (struct frame *f, struct scroll_bar * bar) { - return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE, - /* Position and size of scroll bar. */ - XINT (bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - XINT (bar->top), - XINT (bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - XINT (bar->height), - FRAME_W32_WINDOW (f), - NULL, - hinst, - NULL)); + return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE, + /* Position and size of scroll bar. */ + XINT (bar->left), XINT (bar->top), + XINT (bar->width), XINT (bar->height), + FRAME_W32_WINDOW (f), NULL, hinst, NULL); } static void @@ -1929,7 +1967,7 @@ w32_createwindow (struct frame *f) SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); - SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width); + SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f)); SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f)); /* Enable drag-n-drop. */ @@ -3175,41 +3213,42 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) HIMC context; struct window *w; + /* Implementation note: The code below does something that + one shouldn't do: it accesses the window object from a + separate thread, while the main (a.k.a. "Lisp") thread + runs and can legitimately delete and even GC it. That is + why we are extra careful not to futz with a window that + is different from the one recorded when the system caret + coordinates were last modified. That is also why we are + careful not to move the IME window if the window + described by W was deleted, as indicated by its buffer + field being reset to nil. */ f = x_window_to_frame (dpyinfo, hwnd); + if (!(f && FRAME_LIVE_P (f))) + break; w = XWINDOW (FRAME_SELECTED_WINDOW (f)); + /* Punt if someone changed the frame's selected window + behind our back. */ + if (w != w32_system_caret_window) + break; form.dwStyle = CFS_RECT; form.ptCurrentPos.x = w32_system_caret_x; form.ptCurrentPos.y = w32_system_caret_y; form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0); - -#ifdef ENABLE_CHECKING - /* Temporary code to catch crashes in computing form.rcArea.top. */ - eassert (FRAMEP (w->frame)); - eassert (BUFFERP (w->contents)); - { - int wmbp = WINDOW_MENU_BAR_P (w); - int wtbp = WINDOW_TOOL_BAR_P (w); - struct frame *wf = WINDOW_XFRAME (w); - int fibw = FRAME_INTERNAL_BORDER_WIDTH (wf); - int wtel = WINDOW_TOP_EDGE_LINE (w); - int wflh = FRAME_LINE_HEIGHT (wf); - int wwhlp= WINDOW_WANTS_HEADER_LINE_P (w); - int chlh = CURRENT_HEADER_LINE_HEIGHT (w); - int whlh = (wwhlp ? chlh : 0); - - form.rcArea.top = ((wmbp || wtbp) ? 0 : fibw) + wtel * wflh + whlh; - } -#else form.rcArea.top = (WINDOW_TOP_EDGE_Y (w) - + WINDOW_HEADER_LINE_HEIGHT (w)); -#endif + + w32_system_caret_hdr_height); form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w) - WINDOW_RIGHT_MARGIN_WIDTH (w) - WINDOW_RIGHT_FRINGE_WIDTH (w)); form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w) - - WINDOW_MODE_LINE_HEIGHT (w)); + - WINDOW_BOTTOM_DIVIDER_WIDTH (w) + - w32_system_caret_mode_height); + + /* Punt if the window was deleted behind our back. */ + if (!BUFFERP (w->contents)) + break; context = get_ime_context_fn (hwnd); @@ -3754,7 +3793,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_WINDOWPOSCHANGING: /* Don't restrict the sizing of tip frames. */ - if (hwnd == tip_window) + if (frame_resize_pixelwise || hwnd == tip_window) return 0; /* Don't restrict the sizing of fullscreened frames, allowing them to be @@ -4097,12 +4136,7 @@ w32_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)); my_create_window (f); @@ -4155,9 +4189,6 @@ x_icon (struct frame *f, Lisp_Object parms) block_input (); - if (! EQ (icon_x, Qunbound)) - x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y)); - #if 0 /* TODO */ /* Start up iconic or window? */ x_wm_set_window_state @@ -4216,7 +4247,7 @@ unwind_create_frame (Lisp_Object frame) if (NILP (Fmemq (frame, Vframe_list))) { #ifdef GLYPH_DEBUG - struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f); + struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); #endif x_free_frame_resources (f); @@ -4233,10 +4264,16 @@ unwind_create_frame (Lisp_Object frame) return Qnil; } +static void +do_unwind_create_frame (Lisp_Object frame) +{ + unwind_create_frame (frame); +} + static void x_default_font_parameter (struct frame *f, Lisp_Object parms) { - struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f); + struct w32_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; @@ -4370,10 +4407,10 @@ This function is an internal primitive--use `make-frame' instead. */) if (! STRINGP (f->icon_name)) fset_icon_name (f, Qnil); -/* FRAME_W32_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); #ifdef GLYPH_DEBUG image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; @@ -4389,7 +4426,7 @@ This function is an internal primitive--use `make-frame' instead. */) } else { - f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; + f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.w32->explicit_parent = 0; } @@ -4435,6 +4472,10 @@ This function is an internal primitive--use `make-frame' instead. */) /* Default internalBorderWidth to 0 on Windows to match other programs. */ x_default_parameter (f, parameters, Qinternal_border_width, make_number (0), "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER); + x_default_parameter (f, parameters, Qright_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parameters, Qbottom_divider_width, make_number (0), + NULL, NULL, RES_TYPE_NUMBER); x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright, "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); @@ -4464,6 +4505,20 @@ 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 ... */ + 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); + /* The X resources controlling the menu-bar and tool-bar are processed specially at startup, and reflected in the mode variables; ignore them here. */ @@ -4484,7 +4539,7 @@ This function is an internal primitive--use `make-frame' instead. */) "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; - f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; + f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM); f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW); @@ -4492,6 +4547,7 @@ This function is an internal primitive--use `make-frame' instead. */) f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND); f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT); f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE); + f->output_data.w32->vertical_drag_cursor = w32_load_cursor (IDC_SIZENS); f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor; @@ -4507,7 +4563,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* Now consider the frame official. */ f->terminal->reference_count++; - FRAME_W32_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 window, so that the @@ -4529,12 +4585,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); - - FRAME_LINES (f) = 0; - SET_FRAME_COLS (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); /* Tell the server what size and position, etc, we want, and how badly we want them. This should be done after we have the menu @@ -4591,7 +4646,7 @@ This function is an internal primitive--use `make-frame' instead. */) Lisp_Object x_get_focus_frame (struct frame *frame) { - struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame); + struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); Lisp_Object xfocus; if (! dpyinfo->w32_focus_frame) return Qnil; @@ -4600,22 +4655,13 @@ x_get_focus_frame (struct frame *frame) return xfocus; } -DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, - doc: /* Give FRAME input focus, raising to foreground if necessary. */) - (Lisp_Object frame) -{ - x_focus_on_frame (decode_window_system_frame (frame)); - return Qnil; -} - - DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, doc: /* Internal function called by `color-defined-p', which see. \(Note that the Nextstep version of this function ignores FRAME.) */) (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); @@ -4630,7 +4676,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); @@ -4676,7 +4722,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width, doc: /* Return the width in pixels of DISPLAY. The optional argument DISPLAY specifies which display to ask about. DISPLAY should be either 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 DISPLAY. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object display) { struct w32_display_info *dpyinfo = check_x_display_info (display); @@ -4689,7 +4739,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, doc: /* Return the height in pixels of DISPLAY. The optional argument DISPLAY specifies which display to ask about. DISPLAY should be either 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 DISPLAY. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object display) { struct w32_display_info *dpyinfo = check_x_display_info (display); @@ -4781,41 +4835,46 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height, doc: /* Return the height in millimeters of DISPLAY. The optional argument DISPLAY specifies which display to ask about. DISPLAY should be either 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 DISPLAY. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object display) { struct w32_display_info *dpyinfo = check_x_display_info (display); HDC hdc; - int cap; - - hdc = GetDC (dpyinfo->root_window); + double mm_per_pixel; - cap = GetDeviceCaps (hdc, VERTSIZE); + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE) + / GetDeviceCaps (hdc, VERTRES)); + ReleaseDC (NULL, hdc); - ReleaseDC (dpyinfo->root_window, hdc); - - return make_number (cap); + return make_number (x_display_pixel_height (dpyinfo) * mm_per_pixel + 0.5); } DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, doc: /* Return the width in millimeters of DISPLAY. The optional argument DISPLAY specifies which display to ask about. DISPLAY should be either 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 display) { struct w32_display_info *dpyinfo = check_x_display_info (display); - HDC hdc; - int cap; - - hdc = GetDC (dpyinfo->root_window); + double mm_per_pixel; - cap = GetDeviceCaps (hdc, HORZSIZE); + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE) + / GetDeviceCaps (hdc, HORZRES)); + ReleaseDC (NULL, hdc); - ReleaseDC (dpyinfo->root_window, hdc); - - return make_number (cap); + return make_number (x_display_pixel_width (dpyinfo) * mm_per_pixel + 0.5); } DEFUN ("x-display-backing-store", Fx_display_backing_store, @@ -4867,6 +4926,202 @@ If omitted or nil, that stands for the selected frame's display. */) return Qnil; } +static BOOL CALLBACK +w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData) +{ + Lisp_Object *monitor_list = (Lisp_Object *) dwData; + + *monitor_list = Fcons (make_save_ptr (monitor), *monitor_list); + + return TRUE; +} + +static Lisp_Object +w32_display_monitor_attributes_list (void) +{ + Lisp_Object attributes_list = Qnil, primary_monitor_attributes = Qnil; + Lisp_Object monitor_list = Qnil, monitor_frames, rest, frame; + int i, n_monitors; + HMONITOR *monitors; + struct gcpro gcpro1, gcpro2, gcpro3; + + if (!(enum_display_monitors_fn && get_monitor_info_fn + && monitor_from_window_fn)) + return Qnil; + + if (!enum_display_monitors_fn (NULL, NULL, w32_monitor_enum, + (LPARAM) &monitor_list) + || NILP (monitor_list)) + return Qnil; + + n_monitors = 0; + for (rest = monitor_list; CONSP (rest); rest = XCDR (rest)) + n_monitors++; + + monitors = xmalloc (n_monitors * sizeof (*monitors)); + for (i = 0; i < n_monitors; i++) + { + monitors[i] = XSAVE_POINTER (XCAR (monitor_list), 0); + monitor_list = XCDR (monitor_list); + } + + monitor_frames = Fmake_vector (make_number (n_monitors), Qnil); + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + { + HMONITOR monitor = + monitor_from_window_fn (FRAME_W32_WINDOW (f), + MONITOR_DEFAULT_TO_NEAREST); + + for (i = 0; i < n_monitors; i++) + if (monitors[i] == monitor) + break; + + if (i < n_monitors) + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); + } + } + + GCPRO3 (attributes_list, primary_monitor_attributes, monitor_frames); + + for (i = 0; i < n_monitors; i++) + { + Lisp_Object geometry, workarea, name, attributes = Qnil; + HDC hdc; + int width_mm, height_mm; + struct MONITOR_INFO_EX mi; + + mi.cbSize = sizeof (mi); + if (!get_monitor_info_fn (monitors[i], (struct MONITOR_INFO *) &mi)) + continue; + + hdc = CreateDCA ("DISPLAY", mi.szDevice, NULL, NULL); + if (hdc == NULL) + continue; + width_mm = GetDeviceCaps (hdc, HORZSIZE); + height_mm = GetDeviceCaps (hdc, VERTSIZE); + DeleteDC (hdc); + + attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)), + attributes); + + name = DECODE_SYSTEM (build_unibyte_string (mi.szDevice)); + + attributes = Fcons (Fcons (Qname, name), attributes); + + attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)), + attributes); + + workarea = list4i (mi.rcWork.left, mi.rcWork.top, + mi.rcWork.right - mi.rcWork.left, + mi.rcWork.bottom - mi.rcWork.top); + attributes = Fcons (Fcons (Qworkarea, workarea), attributes); + + geometry = list4i (mi.rcMonitor.left, mi.rcMonitor.top, + mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top); + attributes = Fcons (Fcons (Qgeometry, geometry), attributes); + + if (mi.dwFlags & MONITORINFOF_PRIMARY) + primary_monitor_attributes = attributes; + else + attributes_list = Fcons (attributes, attributes_list); + } + + if (!NILP (primary_monitor_attributes)) + attributes_list = Fcons (primary_monitor_attributes, attributes_list); + + UNGCPRO; + + xfree (monitors); + + return attributes_list; +} + +static Lisp_Object +w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo) +{ + Lisp_Object geometry, workarea, frames, rest, frame, attributes = Qnil; + HDC hdc; + double mm_per_pixel; + int pixel_width, pixel_height, width_mm, height_mm; + RECT workarea_rect; + + /* 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. */ + attributes = Fcons (Fcons (Qname, build_string ("combined screen")), + attributes); + + frames = Qnil; + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_W32_P (f) && !EQ (frame, tip_frame)) + frames = Fcons (frame, frames); + } + attributes = Fcons (Fcons (Qframes, frames), attributes); + + pixel_width = x_display_pixel_width (dpyinfo); + pixel_height = x_display_pixel_height (dpyinfo); + + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE) + / GetDeviceCaps (hdc, HORZRES)); + width_mm = pixel_width * mm_per_pixel + 0.5; + mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE) + / GetDeviceCaps (hdc, VERTRES)); + height_mm = pixel_height * mm_per_pixel + 0.5; + ReleaseDC (NULL, hdc); + attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)), + attributes); + + /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but + we don't care. */ + geometry = list4i (GetSystemMetrics (SM_XVIRTUALSCREEN), + GetSystemMetrics (SM_YVIRTUALSCREEN), + pixel_width, pixel_height); + if (SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0)) + workarea = list4i (workarea_rect.left, workarea_rect.top, + workarea_rect.right - workarea_rect.left, + workarea_rect.bottom - workarea_rect.top); + else + workarea = geometry; + attributes = Fcons (Fcons (Qworkarea, workarea), attributes); + + attributes = Fcons (Fcons (Qgeometry, geometry), attributes); + + return list1 (attributes); +} + +DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list, + Sw32_display_monitor_attributes_list, + 0, 1, 0, + doc: /* Return a list of physical monitor attributes on the W32 display DISPLAY. + +The optional argument DISPLAY specifies which display to ask about. +DISPLAY should be either a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +Internal use only, use `display-monitor-attributes-list' instead. */) + (Lisp_Object display) +{ + struct w32_display_info *dpyinfo = check_x_display_info (display); + Lisp_Object attributes_list; + + block_input (); + attributes_list = w32_display_monitor_attributes_list (); + if (NILP (attributes_list)) + attributes_list = w32_display_monitor_attributes_list_fallback (dpyinfo); + unblock_input (); + + return attributes_list; +} + DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0, doc: /* Set the sound generated when the bell is rung. SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent @@ -4897,23 +5152,10 @@ SOUND is nil to use the normal beep. */) return sound; } - -int -x_pixel_width (register struct frame *f) -{ - return FRAME_PIXEL_WIDTH (f); -} - -int -x_pixel_height (register struct frame *f) -{ - return FRAME_PIXEL_HEIGHT (f); -} - int x_screen_planes (register struct frame *f) { - return FRAME_W32_DISPLAY_INFO (f)->n_planes; + return FRAME_DISPLAY_INFO (f)->n_planes; } /* Return the display structure for the display named NAME. @@ -4922,20 +5164,13 @@ x_screen_planes (register struct frame *f) struct w32_display_info * x_display_info_for_name (Lisp_Object name) { - Lisp_Object names; struct w32_display_info *dpyinfo; CHECK_STRING (name); - for (dpyinfo = &one_w32_display_info, names = w32_display_name_list; - dpyinfo && !NILP (w32_display_name_list); - dpyinfo = dpyinfo->next, names = XCDR (names)) - { - Lisp_Object tem; - tem = Fstring_equal (XCAR (XCAR (names)), name); - if (!NILP (tem)) - return dpyinfo; - } + for (dpyinfo = &one_w32_display_info; 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; @@ -4983,11 +5218,6 @@ terminate Emacs if we can't open the connection. if (! NILP (xrm_string)) CHECK_STRING (xrm_string); -#if 0 - if (! EQ (Vwindow_system, intern ("w32"))) - error ("Not using Microsoft Windows"); -#endif - /* Allow color mapping to be defined externally; first look in user's HOME directory, then in Emacs etc dir for a file called rgb.txt. */ { @@ -5075,11 +5305,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 w32_display_info *wdi; - result = Qnil; - for (tail = w32_display_name_list; CONSP (tail); tail = XCDR (tail)) - result = Fcons (XCAR (XCAR (tail)), result); + for (wdi = x_display_list; wdi; wdi = wdi->next) + result = Fcons (XCAR (wdi->name_list_element), result); return result; } @@ -5268,7 +5498,10 @@ show_hourglass (struct atimer *timer) f = SELECTED_FRAME (); if (!FRAME_W32_P (f)) - return; + { + unblock_input (); + return; + } w32_show_hourglass (f); unblock_input (); @@ -5351,7 +5584,7 @@ Window tip_window; Lisp_Object last_show_tip_args; -static Lisp_Object +static void unwind_create_tip_frame (Lisp_Object frame) { Lisp_Object deleted; @@ -5362,8 +5595,6 @@ unwind_create_tip_frame (Lisp_Object frame) tip_window = NULL; tip_frame = Qnil; } - - return deleted; } @@ -5449,7 +5680,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, dpyinfo_refcount = dpyinfo->reference_count; #endif /* GLYPH_DEBUG */ FRAME_KBOARD (f) = kb; - f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; + f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; f->output_data.w32->explicit_parent = 0; /* Set the name; the functions to which we pass f expect the name to @@ -5496,6 +5727,10 @@ x_create_tip_frame (struct w32_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"), @@ -5518,7 +5753,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, init_frame_faces (f); f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED; - f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; + f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; window_prompting = x_figure_window_size (f, parms, 0); @@ -5540,14 +5775,14 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType", RES_TYPE_SYMBOL); - /* 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). */ + /* 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); FRAME_LINES (f) = 0; SET_FRAME_COLS (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))) @@ -5585,7 +5820,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, /* Now that the frame is official, it counts as a reference to its display. */ - FRAME_W32_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 @@ -5632,8 +5867,8 @@ compute_tip_xy (struct frame *f, /* Default min and max values. */ min_x = 0; min_y = 0; - max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f)); - max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f)); + max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f)); + max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)); block_input (); GetCursorPos (&pt); @@ -5805,6 +6040,10 @@ Text larger than the specified size is clipped. */) parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); if (NILP (Fassq (Qinternal_border_width, parms))) parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); + if (NILP (Fassq (Qright_divider_width, parms))) + parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms); + if (NILP (Fassq (Qbottom_divider_width, parms))) + parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms); if (NILP (Fassq (Qborder_width, parms))) parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); if (NILP (Fassq (Qborder_color, parms))) @@ -5819,13 +6058,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_W32_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) && INTEGERP (XCAR (Vx_max_tooltip_size)) @@ -5842,8 +6083,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) = WINDOW_TOTAL_COLS (w); - adjust_glyphs (f); + adjust_frame_glyphs (f); w->pseudo_window_p = 1; /* Display the tooltip text in a temporary buffer. */ @@ -5907,12 +6151,18 @@ Text larger than the specified size is clipped. */) width of the frame. */ if (seen_reversed_p) { - /* w->total_cols and FRAME_TOTAL_COLS want the width in columns, + /* PXW: Why do we do the pixel-to-cols conversion only if + seen_reversed_p holds? Don't we have to set other fields of + the window/frame structure? + + 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); w->pseudo_window_p = 1; clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); @@ -5941,16 +6191,15 @@ Text larger than the specified size is clipped. */) } } - /* Round up the height to an integral multiple of FRAME_LINE_HEIGHT. */ - if (height % FRAME_LINE_HEIGHT (f) != 0) - height += FRAME_LINE_HEIGHT (f) - height % FRAME_LINE_HEIGHT (f); /* Add the frame's internal border to the width and height the w32 window should have. */ height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); /* Move the tooltip window where the mouse pointer is. Resize and - show it. */ + show it. + + PXW: This should use the frame's pixel coordinates. */ compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); { @@ -6386,7 +6635,7 @@ screen saver if defined. If optional parameter FRAME is not specified, use selected frame. */) (Lisp_Object command, Lisp_Object frame) { - FRAME_PTR f = decode_window_system_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_NUMBER (command); @@ -6726,6 +6975,29 @@ This is a direct interface to the Windows API FindWindow function. */) return Qt; } +DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0, + doc: /* Return boundary rectangle of FRAME in screen coordinates. +FRAME must be a live frame and defaults to the selected one. + +The boundary rectangle is a list of four elements, specifying the left, +top, right and bottom screen coordinates of FRAME including menu and +title bar and decorations. Optional argument CLIENT non-nil means to +return the boundaries of the client rectangle which excludes menu and +title bar and decorations. */) + (Lisp_Object frame, Lisp_Object client) +{ + struct frame *f = decode_live_frame (frame); + RECT rect; + + if (!NILP (client)) + GetClientRect (FRAME_W32_WINDOW (f), &rect); + else + GetWindowRect (FRAME_W32_WINDOW (f), &rect); + + return list4 (make_number (rect.left), make_number (rect.top), + make_number (rect.right), make_number (rect.bottom)); +} + DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0, doc: /* Get power status information from Windows system. @@ -7317,6 +7589,8 @@ frame_parm_handler w32_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, @@ -7359,6 +7633,10 @@ syms_of_w32fns (void) DEFSYM (Qcontrol, "control"); DEFSYM (Qshift, "shift"); DEFSYM (Qfont_param, "font-parameter"); + DEFSYM (Qgeometry, "geometry"); + DEFSYM (Qworkarea, "workarea"); + DEFSYM (Qmm_size, "mm-size"); + DEFSYM (Qframes, "frames"); /* This is the end of symbol initialization. */ @@ -7564,6 +7842,13 @@ or when you set the mouse color. */); 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; #endif DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, @@ -7642,12 +7927,12 @@ only be necessary if the default setting causes problems. */); defsubr (&Sx_close_connection); defsubr (&Sx_display_list); defsubr (&Sx_synchronize); - defsubr (&Sx_focus_frame); /* W32 specific functions */ defsubr (&Sw32_define_rgb_color); defsubr (&Sw32_default_color_map); + defsubr (&Sw32_display_monitor_attributes_list); defsubr (&Sw32_send_sys_command); defsubr (&Sw32_shell_execute); defsubr (&Sw32_register_hot_key); @@ -7656,6 +7941,7 @@ only be necessary if the default setting causes problems. */); defsubr (&Sw32_reconstruct_hot_key); defsubr (&Sw32_toggle_lock_key); defsubr (&Sw32_window_exists_p); + defsubr (&Sw32_frame_rect); defsubr (&Sw32_battery_status); #ifdef WINDOWSNT @@ -7683,59 +7969,35 @@ only be necessary if the default setting causes problems. */); #endif } + -/* - globals_of_w32fns is used to initialize those global variables that - must always be initialized on startup even when the global variable - initialized is non zero (see the function main in emacs.c). - globals_of_w32fns is called from syms_of_w32fns when the global - variable initialized is 0 and directly from main when initialized - is non zero. - */ -void -globals_of_w32fns (void) -{ - HMODULE user32_lib = GetModuleHandle ("user32.dll"); - /* - TrackMouseEvent not available in all versions of Windows, so must load - it dynamically. Do it once, here, instead of every time it is used. - */ - track_mouse_event_fn = (TrackMouseEvent_Proc) - GetProcAddress (user32_lib, "TrackMouseEvent"); - - monitor_from_point_fn = (MonitorFromPoint_Proc) - GetProcAddress (user32_lib, "MonitorFromPoint"); - get_monitor_info_fn = (GetMonitorInfo_Proc) - GetProcAddress (user32_lib, "GetMonitorInfoA"); - monitor_from_window_fn = (MonitorFromWindow_Proc) - GetProcAddress (user32_lib, "MonitorFromWindow"); - - { - HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); - get_composition_string_fn = (ImmGetCompositionString_Proc) - GetProcAddress (imm32_lib, "ImmGetCompositionStringW"); - get_ime_context_fn = (ImmGetContext_Proc) - GetProcAddress (imm32_lib, "ImmGetContext"); - release_ime_context_fn = (ImmReleaseContext_Proc) - GetProcAddress (imm32_lib, "ImmReleaseContext"); - set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc) - GetProcAddress (imm32_lib, "ImmSetCompositionWindow"); - } - DEFVAR_INT ("w32-ansi-code-page", - w32_ansi_code_page, - doc: /* The ANSI code page used by the system. */); - w32_ansi_code_page = GetACP (); - - if (os_subtype == OS_NT) - w32_unicode_gui = 1; - else - w32_unicode_gui = 0; +/* Crashing and reporting backtrace. */ - /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ - InitCommonControls (); +#ifndef CYGWIN +static LONG CALLBACK my_exception_handler (EXCEPTION_POINTERS *); +static LPTOP_LEVEL_EXCEPTION_FILTER prev_exception_handler; +#endif +static DWORD except_code; +static PVOID except_addr; - syms_of_w32uniscribe (); +#ifndef CYGWIN +/* This handler records the exception code and the address where it + was triggered so that this info could be included in the backtrace. + Without that, the backtrace in some cases has no information + whatsoever about the offending code, and looks as if the top-level + exception handler in the MinGW startup code di the one that + crashed. */ +static LONG CALLBACK +my_exception_handler (EXCEPTION_POINTERS * exception_data) +{ + except_code = exception_data->ExceptionRecord->ExceptionCode; + except_addr = exception_data->ExceptionRecord->ExceptionAddress; + + if (prev_exception_handler) + return prev_exception_handler (exception_data); + return EXCEPTION_EXECUTE_HANDLER; } +#endif typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, PULONG); @@ -7792,21 +8054,32 @@ emacs_abort (void) if (i) { + int errfile_fd = -1; + int j; + char buf[sizeof ("\r\nException at this address:\r\n\r\n") + + 2 * INT_BUFSIZE_BOUND (void *)]; #ifdef CYGWIN int stderr_fd = 2; #else HANDLE errout = GetStdHandle (STD_ERROR_HANDLE); int stderr_fd = -1; -#endif - int errfile_fd = -1; - int j; -#ifndef CYGWIN if (errout && errout != INVALID_HANDLE_VALUE) stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY); #endif + + /* We use %p, not 0x%p, as %p produces a leading "0x" on XP, + but not on Windows 7. addr2line doesn't mind a missing + "0x", but will be confused by an extra one. */ + if (except_addr) + sprintf (buf, "\r\nException 0x%lx at this address:\r\n%p\r\n", + except_code, except_addr); if (stderr_fd >= 0) - write (stderr_fd, "\r\nBacktrace:\r\n", 14); + { + if (except_addr) + write (stderr_fd, buf, strlen (buf)); + write (stderr_fd, "\r\nBacktrace:\r\n", 14); + } #ifdef CYGWIN #define _open open #endif @@ -7814,17 +8087,17 @@ emacs_abort (void) if (errfile_fd >= 0) { lseek (errfile_fd, 0L, SEEK_END); + if (except_addr) + write (errfile_fd, buf, strlen (buf)); write (errfile_fd, "\r\nBacktrace:\r\n", 14); } for (j = 0; j < i; j++) { - char buf[INT_BUFSIZE_BOUND (void *)]; - /* stack[] gives the return addresses, whereas we want the address of the call, so decrease each address by approximate size of 1 CALL instruction. */ - sprintf (buf, "0x%p\r\n", (char *)stack[j] - sizeof(void *)); + sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *)); if (stderr_fd >= 0) write (stderr_fd, buf, strlen (buf)); if (errfile_fd >= 0) @@ -7846,6 +8119,72 @@ emacs_abort (void) } } + + +/* Initialization. */ + +/* + globals_of_w32fns is used to initialize those global variables that + must always be initialized on startup even when the global variable + initialized is non zero (see the function main in emacs.c). + globals_of_w32fns is called from syms_of_w32fns when the global + variable initialized is 0 and directly from main when initialized + is non zero. + */ +void +globals_of_w32fns (void) +{ + HMODULE user32_lib = GetModuleHandle ("user32.dll"); + /* + TrackMouseEvent not available in all versions of Windows, so must load + it dynamically. Do it once, here, instead of every time it is used. + */ + track_mouse_event_fn = (TrackMouseEvent_Proc) + GetProcAddress (user32_lib, "TrackMouseEvent"); + + monitor_from_point_fn = (MonitorFromPoint_Proc) + GetProcAddress (user32_lib, "MonitorFromPoint"); + get_monitor_info_fn = (GetMonitorInfo_Proc) + GetProcAddress (user32_lib, "GetMonitorInfoA"); + monitor_from_window_fn = (MonitorFromWindow_Proc) + GetProcAddress (user32_lib, "MonitorFromWindow"); + enum_display_monitors_fn = (EnumDisplayMonitors_Proc) + GetProcAddress (user32_lib, "EnumDisplayMonitors"); + + { + HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); + get_composition_string_fn = (ImmGetCompositionString_Proc) + GetProcAddress (imm32_lib, "ImmGetCompositionStringW"); + get_ime_context_fn = (ImmGetContext_Proc) + GetProcAddress (imm32_lib, "ImmGetContext"); + release_ime_context_fn = (ImmReleaseContext_Proc) + GetProcAddress (imm32_lib, "ImmReleaseContext"); + set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc) + GetProcAddress (imm32_lib, "ImmSetCompositionWindow"); + } + + except_code = 0; + except_addr = 0; +#ifndef CYGWIN + prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler); +#endif + + DEFVAR_INT ("w32-ansi-code-page", + w32_ansi_code_page, + doc: /* The ANSI code page used by the system. */); + w32_ansi_code_page = GetACP (); + + if (os_subtype == OS_NT) + w32_unicode_gui = 1; + else + w32_unicode_gui = 0; + + /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ + InitCommonControls (); + + syms_of_w32uniscribe (); +} + #ifdef NTGUI_UNICODE Lisp_Object