X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/1f635a07be94be671832e5e3db052139265f6445..f0ff1cd5762b2485add7b2e5a1da52eab733a873:/src/w32fns.c diff --git a/src/w32fns.c b/src/w32fns.c index d4e4d78e8d..6e52453cae 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 @@ -1498,14 +1525,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) { @@ -1613,7 +1637,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); do_pending_window_change (0); } - adjust_glyphs (f); + adjust_frame_glyphs (f); } @@ -1655,7 +1679,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) FRAME_TOOL_BAR_LINES (f) = nlines; resize_frame_windows (f, FRAME_LINES (f), 0); - adjust_glyphs (f); + 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 @@ -1728,10 +1752,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 +1784,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 +1793,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); } @@ -1866,16 +1890,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 @@ -3175,39 +3194,41 @@ 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. */ - { - 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)); + - 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); @@ -4095,12 +4116,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); @@ -4153,9 +4169,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 @@ -4214,7 +4227,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); @@ -4231,10 +4244,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; @@ -4368,10 +4387,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; @@ -4387,7 +4406,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; } @@ -4482,7 +4501,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); @@ -4505,7 +4524,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 @@ -4589,7 +4608,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; @@ -4598,22 +4617,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); @@ -4628,7 +4638,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); @@ -4674,7 +4684,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); @@ -4687,7 +4701,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); @@ -4779,41 +4797,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); - - cap = GetDeviceCaps (hdc, VERTSIZE); + double mm_per_pixel; - ReleaseDC (dpyinfo->root_window, hdc); + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE) + / GetDeviceCaps (hdc, VERTRES)); + ReleaseDC (NULL, 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; + double mm_per_pixel; - hdc = GetDC (dpyinfo->root_window); + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE) + / GetDeviceCaps (hdc, HORZRES)); + ReleaseDC (NULL, hdc); - cap = GetDeviceCaps (hdc, HORZSIZE); - - 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, @@ -4865,6 +4888,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 @@ -4895,23 +5114,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. @@ -4981,11 +5187,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. */ { @@ -5266,7 +5467,10 @@ show_hourglass (struct atimer *timer) f = SELECTED_FRAME (); if (!FRAME_W32_P (f)) - return; + { + unblock_input (); + return; + } w32_show_hourglass (f); unblock_input (); @@ -5349,7 +5553,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; @@ -5360,8 +5564,6 @@ unwind_create_tip_frame (Lisp_Object frame) tip_window = NULL; tip_frame = Qnil; } - - return deleted; } @@ -5447,7 +5649,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 @@ -5516,7 +5718,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); @@ -5583,7 +5785,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 @@ -5630,8 +5832,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); @@ -5817,7 +6019,7 @@ 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. */ @@ -5841,7 +6043,7 @@ Text larger than the specified size is clipped. */) } 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. */ @@ -5910,7 +6112,7 @@ Text larger than the specified size is clipped. */) width /= WINDOW_FRAME_COLUMN_WIDTH (w); w->total_cols = width; FRAME_TOTAL_COLS (f) = width; - adjust_glyphs (f); + adjust_frame_glyphs (f); w->pseudo_window_p = 1; clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); @@ -6384,7 +6586,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); @@ -7357,6 +7559,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. */ @@ -7640,12 +7846,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); @@ -7707,6 +7913,8 @@ globals_of_w32fns (void) 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");