X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/830e46e61ba1316e771c72a15e709d3d12e150b7..aa30fa6f3a4273adcfa1cba183a74a5aeb47b463:/src/w32fns.c?ds=sidebyside diff --git a/src/w32fns.c b/src/w32fns.c index 6c098cae3a..a8b444e040 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -95,10 +95,6 @@ static HWND hourglass_hwnd = NULL; #define IDC_HAND MAKEINTRESOURCE(32649) #endif -/* Nonzero if using Windows. */ - -static int w32_in_use; - Lisp_Object Qsuppress_icon; Lisp_Object Qundefined_color; Lisp_Object Qcancel_timer; @@ -110,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. */ @@ -135,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 @@ -145,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); @@ -161,6 +179,12 @@ typedef HWND (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context, typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags); 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; @@ -169,6 +193,8 @@ ImmReleaseContext_Proc release_ime_context_fn = NULL; 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 @@ -239,37 +265,6 @@ HINSTANCE hinst = NULL; static unsigned int sound_type = 0xFFFFFFFF; #define MB_EMACS_SILENT (0xFFFFFFFF - 1) - -/* Error if we are not connected to MS-Windows. */ -void -check_w32 (void) -{ - if (! w32_in_use) - error ("MS-Windows not in use or not initialized"); -} - -/* Nonzero if we can use mouse menus. - You should not call this unless HAVE_MENUS is defined. */ - -int -have_menus_p (void) -{ - return w32_in_use; -} - -/* Extract a frame as a FRAME_PTR, defaulting to the selected frame - and checking validity for W32. */ - -FRAME_PTR -check_x_frame (Lisp_Object frame) -{ - struct frame *f = decode_live_frame (frame); - - if (! FRAME_W32_P (f)) - error ("Non-W32 frame used"); - return f; -} - /* Let the user specify a display with a frame. nil stands for the selected frame--or, if that is not a w32 frame, the first display on the list. */ @@ -290,7 +285,7 @@ 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); @@ -323,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 *); @@ -349,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; @@ -371,6 +366,66 @@ x_real_positions (FRAME_PTR f, int *xptr, int *yptr) *yptr = rect.top; } +/* Returns the window rectangle appropriate for the given fullscreen mode. + The normal rect parameter was the window's rectangle prior to entering + fullscreen mode. If multiple monitor support is available, the nearest + monitor to the window is chosen. */ + +void +w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal, RECT *rect) +{ + struct MONITOR_INFO mi = { sizeof(mi) }; + if (monitor_from_window_fn && get_monitor_info_fn) + { + HMONITOR monitor = + monitor_from_window_fn (hwnd, MONITOR_DEFAULT_TO_NEAREST); + get_monitor_info_fn (monitor, &mi); + } + else + { + mi.rcMonitor.left = 0; + mi.rcMonitor.top = 0; + mi.rcMonitor.right = GetSystemMetrics (SM_CXSCREEN); + mi.rcMonitor.bottom = GetSystemMetrics (SM_CYSCREEN); + mi.rcWork.left = 0; + mi.rcWork.top = 0; + mi.rcWork.right = GetSystemMetrics (SM_CXMAXIMIZED); + mi.rcWork.bottom = GetSystemMetrics (SM_CYMAXIMIZED); + } + + switch (fsmode) + { + case FULLSCREEN_BOTH: + rect->left = mi.rcMonitor.left; + rect->top = mi.rcMonitor.top; + rect->right = mi.rcMonitor.right; + rect->bottom = mi.rcMonitor.bottom; + break; + case FULLSCREEN_MAXIMIZED: + rect->left = mi.rcWork.left; + rect->top = mi.rcWork.top; + rect->right = mi.rcWork.right; + rect->bottom = mi.rcWork.bottom; + break; + case FULLSCREEN_WIDTH: + rect->left = mi.rcWork.left; + rect->top = normal.top; + rect->right = mi.rcWork.right; + rect->bottom = normal.bottom; + break; + case FULLSCREEN_HEIGHT: + rect->left = normal.left; + rect->top = mi.rcWork.top; + rect->right = normal.right; + rect->bottom = mi.rcWork.bottom; + break; + case FULLSCREEN_NONE: + default: + *rect = normal; + break; + } +} + DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color, @@ -964,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; @@ -1014,7 +1069,7 @@ 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; @@ -1045,7 +1100,7 @@ w32_map_color (FRAME_PTR f, COLORREF color) } 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; @@ -1098,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; @@ -1169,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; @@ -1470,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) { @@ -1585,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); } @@ -1627,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 @@ -1721,11 +1773,9 @@ x_set_name (struct frame *f, Lisp_Object name, int explicit) if (FRAME_W32_WINDOW (f)) { - if (STRING_MULTIBYTE (name)) - name = ENCODE_SYSTEM (name); - block_input (); - SetWindowText (FRAME_W32_WINDOW (f), SDATA (name)); + GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f), + GUI_SDATA (GUI_ENCODE_SYSTEM (name))); unblock_input (); } } @@ -1734,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); } @@ -1743,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); } @@ -1767,11 +1817,9 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) if (FRAME_W32_WINDOW (f)) { - if (STRING_MULTIBYTE (name)) - name = ENCODE_SYSTEM (name); - block_input (); - SetWindowText (FRAME_W32_WINDOW (f), SDATA (name)); + GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f), + GUI_SDATA (GUI_ENCODE_SYSTEM (name))); unblock_input (); } } @@ -3151,8 +3199,24 @@ 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; @@ -3160,12 +3224,16 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0); form.rcArea.top = (WINDOW_TOP_EDGE_Y (w) - + WINDOW_HEADER_LINE_HEIGHT (w)); + + 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); @@ -3712,6 +3780,13 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Don't restrict the sizing of tip frames. */ if (hwnd == tip_window) return 0; + + /* Don't restrict the sizing of fullscreened frames, allowing them to be + flush with the sides of the screen. */ + f = x_window_to_frame (dpyinfo, hwnd); + if (f && FRAME_PREV_FSMODE (f) != FULLSCREEN_NONE) + return 0; + { WINDOWPLACEMENT wp; LPWINDOWPOS lppos = (WINDOWPOS *) lParam; @@ -4046,12 +4121,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); @@ -4104,9 +4174,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 @@ -4182,6 +4249,12 @@ 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) { @@ -4322,7 +4395,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */ /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */ - record_unwind_protect (unwind_create_frame, frame); + record_unwind_protect (do_unwind_create_frame, frame); #ifdef GLYPH_DEBUG image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; @@ -4357,9 +4430,6 @@ This function is an internal primitive--use `make-frame' instead. */) specbind (Qx_resource_name, name); } - f->resx = dpyinfo->resx; - f->resy = dpyinfo->resy; - if (uniscribe_available) register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); @@ -4556,7 +4626,7 @@ 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 (check_x_frame (frame)); + x_focus_on_frame (decode_window_system_frame (frame)); return Qnil; } @@ -4567,7 +4637,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 = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_STRING (color); @@ -4582,17 +4652,14 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { XColor foo; - FRAME_PTR f = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_STRING (color); if (w32_defined_color (f, SDATA (color), &foo, 0)) - return list3 (make_number ((GetRValue (foo.pixel) << 8) - | GetRValue (foo.pixel)), - make_number ((GetGValue (foo.pixel) << 8) - | GetGValue (foo.pixel)), - make_number ((GetBValue (foo.pixel) << 8) - | GetBValue (foo.pixel))); + return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel), + (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel), + (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel)); else return Qnil; } @@ -4631,7 +4698,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); @@ -4644,7 +4715,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); @@ -4718,9 +4793,7 @@ DISPLAY should be either a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) (Lisp_Object display) { - return Fcons (make_number (w32_major_version), - Fcons (make_number (w32_minor_version), - Fcons (make_number (w32_build_number), Qnil))); + return list3i (w32_major_version, w32_minor_version, w32_build_number); } DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, @@ -4738,41 +4811,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; - - hdc = GetDC (dpyinfo->root_window); - - cap = GetDeviceCaps (hdc, HORZSIZE); + double mm_per_pixel; - ReleaseDC (dpyinfo->root_window, hdc); + hdc = GetDC (NULL); + mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE) + / GetDeviceCaps (hdc, HORZRES)); + ReleaseDC (NULL, 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, @@ -4824,6 +4902,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 @@ -4854,19 +5128,6 @@ 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) { @@ -4905,7 +5166,6 @@ x_display_info_for_name (Lisp_Object name) if (dpyinfo == 0) error ("Cannot connect to server %s", SDATA (name)); - w32_in_use = 1; XSETFASTINT (Vwindow_system_version, w32_major_version); return dpyinfo; @@ -4935,17 +5195,12 @@ terminate Emacs if we can't open the connection. /* If initialization has already been done, return now to avoid overwriting critical parts of one_w32_display_info. */ - if (w32_in_use) + if (window_system_available (NULL)) return Qnil; 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. */ { @@ -5004,8 +5259,6 @@ terminate Emacs if we can't open the connection. error ("Cannot connect to server %s", SDATA (display)); } - w32_in_use = 1; - XSETFASTINT (Vwindow_system_version, w32_major_version); return Qnil; } @@ -5089,7 +5342,7 @@ FRAME. Default is to change on the edit X window. */) (Lisp_Object prop, Lisp_Object value, Lisp_Object frame, Lisp_Object type, Lisp_Object format, Lisp_Object outer_p) { - struct frame *f = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); Atom prop_atom; CHECK_STRING (prop); @@ -5115,7 +5368,7 @@ DEFUN ("x-delete-window-property", Fx_delete_window_property, FRAME nil or omitted means use the selected frame. Value is PROP. */) (Lisp_Object prop, Lisp_Object frame) { - struct frame *f = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); Atom prop_atom; CHECK_STRING (prop); @@ -5151,7 +5404,7 @@ 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 = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); Atom prop_atom; int rc; Lisp_Object prop_value = Qnil; @@ -5311,7 +5564,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; @@ -5322,8 +5575,6 @@ unwind_create_tip_frame (Lisp_Object frame) tip_window = NULL; tip_frame = Qnil; } - - return deleted; } @@ -5352,8 +5603,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object buffer; struct buffer *old_buffer; - check_w32 (); - /* Use this general default value to start with until we know if this frame has a specified name. */ Vx_resource_name = Vinvocation_name; @@ -5429,9 +5678,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, specbind (Qx_resource_name, name); } - f->resx = dpyinfo->resx; - f->resy = dpyinfo->resy; - if (uniscribe_available) register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); @@ -5700,7 +5946,7 @@ Text larger than the specified size is clipped. */) GCPRO4 (string, parms, frame, timeout); CHECK_STRING (string); - f = check_x_frame (frame); + f = decode_window_system_frame (frame); if (NILP (timeout)) timeout = make_number (5); else @@ -5789,8 +6035,8 @@ Text larger than the specified size is clipped. */) /* Set up the frame's root window. */ w = XWINDOW (FRAME_ROOT_WINDOW (f)); - wset_left_col (w, make_number (0)); - wset_top_line (w, make_number (0)); + w->left_col = 0; + w->top_line = 0; if (CONSP (Vx_max_tooltip_size) && INTEGERP (XCAR (Vx_max_tooltip_size)) @@ -5798,22 +6044,22 @@ Text larger than the specified size is clipped. */) && INTEGERP (XCDR (Vx_max_tooltip_size)) && XINT (XCDR (Vx_max_tooltip_size)) > 0) { - wset_total_cols (w, XCAR (Vx_max_tooltip_size)); - wset_total_lines (w, XCDR (Vx_max_tooltip_size)); + w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size)); + w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size)); } else { - wset_total_cols (w, make_number (80)); - wset_total_lines (w, make_number (40)); + w->total_cols = 80; + w->total_lines = 40; } - FRAME_TOTAL_COLS (f) = XINT (w->total_cols); - adjust_glyphs (f); + FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w); + adjust_frame_glyphs (f); w->pseudo_window_p = 1; /* Display the tooltip text in a temporary buffer. */ old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer)); + set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents)); bset_truncate_lines (current_buffer, Qnil); clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); @@ -5829,7 +6075,7 @@ Text larger than the specified size is clipped. */) int row_width; /* Stop at the first empty row at the end. */ - if (!row->enabled_p || !row->displays_text_p) + if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) break; /* Let the row go over the full width of the frame. */ @@ -5875,9 +6121,9 @@ Text larger than the specified size is clipped. */) /* w->total_cols and FRAME_TOTAL_COLS want the width in columns, not in pixels. */ width /= WINDOW_FRAME_COLUMN_WIDTH (w); - wset_total_cols (w, make_number (width)); + 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); @@ -5890,7 +6136,7 @@ Text larger than the specified size is clipped. */) struct glyph *last; int row_width; - if (!row->enabled_p || !row->displays_text_p) + if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) break; row->full_width_p = 1; row_width = row->pixel_width; @@ -6011,14 +6257,6 @@ Value is t if tooltip was open, nil otherwise. */) #define FILE_NAME_COMBO_BOX cmb13 #define FILE_NAME_LIST lst1 -#ifdef NTGUI_UNICODE -#define GUISTR(x) (L ## x) -typedef wchar_t guichar_t; -#else /* !NTGUI_UNICODE */ -#define GUISTR(x) x -typedef char guichar_t; -#endif /* NTGUI_UNICODE */ - /* Callback for altering the behavior of the Open File dialog. Makes the Filename text field contain "Current Directory" and be read-only when "Directories" is selected in the filter. This @@ -6235,11 +6473,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) block_input (); file_details->lpfnHook = file_dialog_callback; -#ifdef NTGUI_UNICODE - file_opened = GetOpenFileNameW (file_details); -#else /* !NTGUI_UNICODE */ - file_opened = GetOpenFileNameA (file_details); -#endif /* NTGUI_UNICODE */ + file_opened = GUI_FN (GetOpenFileName) (file_details); unblock_input (); unbind_to (count, Qnil); } @@ -6248,13 +6482,9 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) { /* Get an Emacs string from the value Windows gave us. */ #ifdef NTGUI_UNICODE - filename = from_unicode ( - make_unibyte_string ( - (char*) filename_buf, - /* we get one of the two final 0 bytes for free. */ - 1 + sizeof (wchar_t) * wcslen (filename_buf))); + filename = from_unicode_buffer (filename_buf); #else /* !NTGUI_UNICODE */ - dostounix_filename (filename_buf); + dostounix_filename (filename_buf, 0); filename = DECODE_FILE (build_string (filename_buf)); #endif /* NTGUI_UNICODE */ @@ -6367,7 +6597,7 @@ screen saver if defined. If optional parameter FRAME is not specified, use selected frame. */) (Lisp_Object command, Lisp_Object frame) { - FRAME_PTR f = check_x_frame (frame); + struct frame *f = decode_window_system_frame (frame); CHECK_NUMBER (command); @@ -6426,20 +6656,29 @@ an integer representing a ShowWindow flag: CHECK_STRING (document); /* Encode filename, current directory and parameters. */ - current_dir = ENCODE_FILE (BVAR (current_buffer, directory)); - document = ENCODE_FILE (document); + current_dir = BVAR (current_buffer, directory); + +#ifdef CYGWIN + current_dir = Fcygwin_convert_file_name_to_windows (current_dir, Qt); + if (STRINGP (document)) + document = Fcygwin_convert_file_name_to_windows (document, Qt); +#endif /* CYGWIN */ + + current_dir = GUI_ENCODE_FILE (current_dir); + if (STRINGP (document)) + document = GUI_ENCODE_FILE (document); if (STRINGP (parameters)) - parameters = ENCODE_SYSTEM (parameters); - - if ((int) ShellExecute (NULL, - (STRINGP (operation) ? - SDATA (operation) : NULL), - SDATA (document), - (STRINGP (parameters) ? - SDATA (parameters) : NULL), - SDATA (current_dir), - (INTEGERP (show_flag) ? - XINT (show_flag) : SW_SHOWDEFAULT)) + parameters = GUI_ENCODE_SYSTEM (parameters); + + if ((int) GUI_FN (ShellExecute) (NULL, + (STRINGP (operation) ? + GUI_SDATA (operation) : NULL), + GUI_SDATA (document), + (STRINGP (parameters) ? + GUI_SDATA (parameters) : NULL), + GUI_SDATA (current_dir), + (INTEGERP (show_flag) ? + XINT (show_flag) : SW_SHOWDEFAULT)) > 32) return Qt; errstr = w32_strerror (0); @@ -6484,12 +6723,12 @@ w32_parse_hot_key (Lisp_Object key) CHECK_VECTOR (key); - if (XFASTINT (Flength (key)) != 1) + if (ASIZE (key) != 1) return Qnil; GCPRO1 (key); - c = Faref (key, make_number (0)); + c = AREF (key, 0); if (CONSP (c) && lucid_event_type_list_p (c)) c = Fevent_convert_list (c); @@ -6808,6 +7047,7 @@ The following %-sequences are provided: } +#ifdef WINDOWSNT DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, doc: /* Return storage information about the file system FILENAME is on. Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total @@ -6903,6 +7143,8 @@ If the underlying system call fails, value is nil. */) return value; } +#endif /* WINDOWSNT */ + DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name, 0, 0, 0, doc: /* Return the name of Windows default printer device. */) @@ -7313,8 +7555,6 @@ void syms_of_w32fns (void) { globals_of_w32fns (); - /* This is zero if not using MS-Windows. */ - w32_in_use = 0; track_mouse_window = NULL; w32_visible_system_caret_hwnd = NULL; @@ -7330,6 +7570,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. */ @@ -7619,6 +7863,7 @@ only be necessary if the default setting causes problems. */); 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); @@ -7629,12 +7874,13 @@ only be necessary if the default setting causes problems. */); defsubr (&Sw32_window_exists_p); defsubr (&Sw32_battery_status); +#ifdef WINDOWSNT defsubr (&Sfile_system_info); +#endif + defsubr (&Sdefault_printer_name); defsubr (&Sset_message_beep); - check_window_system_func = check_w32; - hourglass_hwnd = NULL; defsubr (&Sx_show_tip); @@ -7677,6 +7923,10 @@ globals_of_w32fns (void) 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"); @@ -7775,6 +8025,9 @@ emacs_abort (void) #endif if (stderr_fd >= 0) write (stderr_fd, "\r\nBacktrace:\r\n", 14); +#ifdef CYGWIN +#define _open open +#endif errfile_fd = _open ("emacs_backtrace.txt", O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE); if (errfile_fd >= 0) { @@ -7810,3 +8063,15 @@ emacs_abort (void) } } } + +#ifdef NTGUI_UNICODE + +Lisp_Object +ntgui_encode_system (Lisp_Object str) +{ + Lisp_Object encoded; + to_unicode (str, &encoded); + return encoded; +} + +#endif /* NTGUI_UNICODE */