aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2013-07-04 19:25:54 +0900
committerYAMAMOTO Mitsuharu2013-07-04 19:25:54 +0900
commitcf13177e99d20e8db632ad6ed5defd3818f7d901 (patch)
tree8cbc52eb53375dfbb2eb4eba3dff92453385e186 /src
parent46e4f8217a5379bfab2a0f9c78e2a6a23a9d3cf1 (diff)
downloademacs-cf13177e99d20e8db632ad6ed5defd3818f7d901.tar.gz
emacs-cf13177e99d20e8db632ad6ed5defd3818f7d901.zip
Add multi-monitor support on W32.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog24
-rw-r--r--src/w32fns.c281
-rw-r--r--src/w32term.c27
3 files changed, 307 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 416e60f30a4..9012f5ba16a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,27 @@
12013-07-04 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2
3 * w32fns.c (Qgeometry, Qworkarea, Qmm_size, Qframes): New variables.
4 (syms_of_w32fns): DEFSYM them.
5 (MONITORINFOF_PRIMARY, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN)
6 (CCHDEVICENAME): Define macros if not defined.
7 (struct MONITOR_INFO_EX): New struct.
8 (MonitorEnum_Proc, EnumDisplayMonitors_Proc): New prototypes.
9 (enum_display_monitors_fn): New variable.
10 (globals_of_w32fns): Initialize it.
11 (Fx_display_pixel_width, Fx_display_pixel_height)
12 (Fx_display_mm_height, Fx_display_mm_width): Mention behavior on
13 multi-monitor setups in docstrings.
14 (Fx_display_mm_height, Fx_display_mm_width): Approximate whole
15 screen size by primary monitor's millimeter per pixel.
16 (w32_monitor_enum, w32_display_monitor_attributes_list)
17 (w32_display_monitor_attributes_list_fallback)
18 (Fw32_display_monitor_attributes_list): New functions.
19 (syms_of_w32fns): Defsubr Sw32_display_monitor_attributes_list.
20
21 * w32term.c (SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN): Define macros
22 if not defined.
23 (x_display_pixel_height, x_display_pixel_width): Use GetSystemMetrics.
24
12013-07-04 Michael Albinus <michael.albinus@gmx.de> 252013-07-04 Michael Albinus <michael.albinus@gmx.de>
2 26
3 * fileio.c (Qfile_notify_error): New error symbol. 27 * fileio.c (Qfile_notify_error): New error symbol.
diff --git a/src/w32fns.c b/src/w32fns.c
index 46fb02d96a1..3fa23c166e2 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -106,6 +106,7 @@ Lisp_Object Qalt;
106Lisp_Object Qctrl; 106Lisp_Object Qctrl;
107Lisp_Object Qcontrol; 107Lisp_Object Qcontrol;
108Lisp_Object Qshift; 108Lisp_Object Qshift;
109static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
109 110
110 111
111/* Prefix for system colors. */ 112/* Prefix for system colors. */
@@ -131,6 +132,15 @@ static HWND track_mouse_window;
131#ifndef MONITOR_DEFAULT_TO_NEAREST 132#ifndef MONITOR_DEFAULT_TO_NEAREST
132#define MONITOR_DEFAULT_TO_NEAREST 2 133#define MONITOR_DEFAULT_TO_NEAREST 2
133#endif 134#endif
135#ifndef MONITORINFOF_PRIMARY
136#define MONITORINFOF_PRIMARY 1
137#endif
138#ifndef SM_XVIRTUALSCREEN
139#define SM_XVIRTUALSCREEN 76
140#endif
141#ifndef SM_YVIRTUALSCREEN
142#define SM_YVIRTUALSCREEN 77
143#endif
134/* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't. 144/* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
135 To avoid a compile error on one or the other, redefine with a new name. */ 145 To avoid a compile error on one or the other, redefine with a new name. */
136struct MONITOR_INFO 146struct MONITOR_INFO
@@ -141,6 +151,18 @@ struct MONITOR_INFO
141 DWORD dwFlags; 151 DWORD dwFlags;
142}; 152};
143 153
154#ifndef CCHDEVICENAME
155#define CCHDEVICENAME 32
156#endif
157struct MONITOR_INFO_EX
158{
159 DWORD cbSize;
160 RECT rcMonitor;
161 RECT rcWork;
162 DWORD dwFlags;
163 char szDevice[CCHDEVICENAME];
164};
165
144/* Reportedly, MSVC does not have this in its headers. */ 166/* Reportedly, MSVC does not have this in its headers. */
145#if defined (_MSC_VER) && _WIN32_WINNT < 0x0500 167#if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
146DECLARE_HANDLE(HMONITOR); 168DECLARE_HANDLE(HMONITOR);
@@ -159,6 +181,10 @@ typedef BOOL (WINAPI * GetMonitorInfo_Proc)
159 (IN HMONITOR monitor, OUT struct MONITOR_INFO* info); 181 (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
160typedef HMONITOR (WINAPI * MonitorFromWindow_Proc) 182typedef HMONITOR (WINAPI * MonitorFromWindow_Proc)
161 (IN HWND hwnd, IN DWORD dwFlags); 183 (IN HWND hwnd, IN DWORD dwFlags);
184typedef BOOL CALLBACK (* MonitorEnum_Proc)
185 (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData);
186typedef BOOL (WINAPI * EnumDisplayMonitors_Proc)
187 (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
162 188
163TrackMouseEvent_Proc track_mouse_event_fn = NULL; 189TrackMouseEvent_Proc track_mouse_event_fn = NULL;
164ImmGetCompositionString_Proc get_composition_string_fn = NULL; 190ImmGetCompositionString_Proc get_composition_string_fn = NULL;
@@ -168,6 +194,7 @@ ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
168MonitorFromPoint_Proc monitor_from_point_fn = NULL; 194MonitorFromPoint_Proc monitor_from_point_fn = NULL;
169GetMonitorInfo_Proc get_monitor_info_fn = NULL; 195GetMonitorInfo_Proc get_monitor_info_fn = NULL;
170MonitorFromWindow_Proc monitor_from_window_fn = NULL; 196MonitorFromWindow_Proc monitor_from_window_fn = NULL;
197EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL;
171 198
172#ifdef NTGUI_UNICODE 199#ifdef NTGUI_UNICODE
173#define unicode_append_menu AppendMenuW 200#define unicode_append_menu AppendMenuW
@@ -4674,7 +4701,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
4674 doc: /* Return the width in pixels of DISPLAY. 4701 doc: /* Return the width in pixels of DISPLAY.
4675The optional argument DISPLAY specifies which display to ask about. 4702The optional argument DISPLAY specifies which display to ask about.
4676DISPLAY should be either a frame or a display name (a string). 4703DISPLAY should be either a frame or a display name (a string).
4677If omitted or nil, that stands for the selected frame's display. */) 4704If omitted or nil, that stands for the selected frame's display.
4705
4706On \"multi-monitor\" setups this refers to the pixel width for all
4707physical monitors associated with DISPLAY. To get information for
4708each physical monitor, use `display-monitor-attributes-list'. */)
4678 (Lisp_Object display) 4709 (Lisp_Object display)
4679{ 4710{
4680 struct w32_display_info *dpyinfo = check_x_display_info (display); 4711 struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4687,7 +4718,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4687 doc: /* Return the height in pixels of DISPLAY. 4718 doc: /* Return the height in pixels of DISPLAY.
4688The optional argument DISPLAY specifies which display to ask about. 4719The optional argument DISPLAY specifies which display to ask about.
4689DISPLAY should be either a frame or a display name (a string). 4720DISPLAY should be either a frame or a display name (a string).
4690If omitted or nil, that stands for the selected frame's display. */) 4721If omitted or nil, that stands for the selected frame's display.
4722
4723On \"multi-monitor\" setups this refers to the pixel height for all
4724physical monitors associated with DISPLAY. To get information for
4725each physical monitor, use `display-monitor-attributes-list'. */)
4691 (Lisp_Object display) 4726 (Lisp_Object display)
4692{ 4727{
4693 struct w32_display_info *dpyinfo = check_x_display_info (display); 4728 struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4779,41 +4814,46 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height,
4779 doc: /* Return the height in millimeters of DISPLAY. 4814 doc: /* Return the height in millimeters of DISPLAY.
4780The optional argument DISPLAY specifies which display to ask about. 4815The optional argument DISPLAY specifies which display to ask about.
4781DISPLAY should be either a frame or a display name (a string). 4816DISPLAY should be either a frame or a display name (a string).
4782If omitted or nil, that stands for the selected frame's display. */) 4817If omitted or nil, that stands for the selected frame's display.
4818
4819On \"multi-monitor\" setups this refers to the height in millimeters for
4820all physical monitors associated with DISPLAY. To get information
4821for each physical monitor, use `display-monitor-attributes-list'. */)
4783 (Lisp_Object display) 4822 (Lisp_Object display)
4784{ 4823{
4785 struct w32_display_info *dpyinfo = check_x_display_info (display); 4824 struct w32_display_info *dpyinfo = check_x_display_info (display);
4786 HDC hdc; 4825 HDC hdc;
4787 int cap; 4826 double mm_per_pixel;
4788
4789 hdc = GetDC (dpyinfo->root_window);
4790 4827
4791 cap = GetDeviceCaps (hdc, VERTSIZE); 4828 hdc = GetDC (NULL);
4829 mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
4830 / GetDeviceCaps (hdc, VERTRES));
4831 ReleaseDC (NULL, hdc);
4792 4832
4793 ReleaseDC (dpyinfo->root_window, hdc); 4833 return make_number (x_display_pixel_height (dpyinfo) * mm_per_pixel + 0.5);
4794
4795 return make_number (cap);
4796} 4834}
4797 4835
4798DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, 4836DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4799 doc: /* Return the width in millimeters of DISPLAY. 4837 doc: /* Return the width in millimeters of DISPLAY.
4800The optional argument DISPLAY specifies which display to ask about. 4838The optional argument DISPLAY specifies which display to ask about.
4801DISPLAY should be either a frame or a display name (a string). 4839DISPLAY should be either a frame or a display name (a string).
4802If omitted or nil, that stands for the selected frame's display. */) 4840If omitted or nil, that stands for the selected frame's display.
4841
4842On \"multi-monitor\" setups this refers to the width in millimeters for
4843all physical monitors associated with TERMINAL. To get information
4844for each physical monitor, use `display-monitor-attributes-list'. */)
4803 (Lisp_Object display) 4845 (Lisp_Object display)
4804{ 4846{
4805 struct w32_display_info *dpyinfo = check_x_display_info (display); 4847 struct w32_display_info *dpyinfo = check_x_display_info (display);
4806
4807 HDC hdc; 4848 HDC hdc;
4808 int cap; 4849 double mm_per_pixel;
4809 4850
4810 hdc = GetDC (dpyinfo->root_window); 4851 hdc = GetDC (NULL);
4852 mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
4853 / GetDeviceCaps (hdc, HORZRES));
4854 ReleaseDC (NULL, hdc);
4811 4855
4812 cap = GetDeviceCaps (hdc, HORZSIZE); 4856 return make_number (x_display_pixel_width (dpyinfo) * mm_per_pixel + 0.5);
4813
4814 ReleaseDC (dpyinfo->root_window, hdc);
4815
4816 return make_number (cap);
4817} 4857}
4818 4858
4819DEFUN ("x-display-backing-store", Fx_display_backing_store, 4859DEFUN ("x-display-backing-store", Fx_display_backing_store,
@@ -4865,6 +4905,202 @@ If omitted or nil, that stands for the selected frame's display. */)
4865 return Qnil; 4905 return Qnil;
4866} 4906}
4867 4907
4908static BOOL CALLBACK
4909w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData)
4910{
4911 Lisp_Object *monitor_list = (Lisp_Object *) dwData;
4912
4913 *monitor_list = Fcons (make_save_pointer (monitor), *monitor_list);
4914
4915 return TRUE;
4916}
4917
4918static Lisp_Object
4919w32_display_monitor_attributes_list (void)
4920{
4921 Lisp_Object attributes_list = Qnil, primary_monitor_attributes = Qnil;
4922 Lisp_Object monitor_list = Qnil, monitor_frames, rest, frame;
4923 int i, n_monitors;
4924 HMONITOR *monitors;
4925 struct gcpro gcpro1, gcpro2, gcpro3;
4926
4927 if (!(enum_display_monitors_fn && get_monitor_info_fn
4928 && monitor_from_window_fn))
4929 return Qnil;
4930
4931 if (!enum_display_monitors_fn (NULL, NULL, w32_monitor_enum,
4932 (LPARAM) &monitor_list)
4933 || NILP (monitor_list))
4934 return Qnil;
4935
4936 n_monitors = 0;
4937 for (rest = monitor_list; CONSP (rest); rest = XCDR (rest))
4938 n_monitors++;
4939
4940 monitors = xmalloc (n_monitors * sizeof (*monitors));
4941 for (i = 0; i < n_monitors; i++)
4942 {
4943 monitors[i] = XSAVE_POINTER (XCAR (monitor_list), 0);
4944 monitor_list = XCDR (monitor_list);
4945 }
4946
4947 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4948 FOR_EACH_FRAME (rest, frame)
4949 {
4950 struct frame *f = XFRAME (frame);
4951
4952 if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
4953 {
4954 HMONITOR monitor =
4955 monitor_from_window_fn (FRAME_W32_WINDOW (f),
4956 MONITOR_DEFAULT_TO_NEAREST);
4957
4958 for (i = 0; i < n_monitors; i++)
4959 if (monitors[i] == monitor)
4960 break;
4961
4962 if (i < n_monitors)
4963 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4964 }
4965 }
4966
4967 GCPRO3 (attributes_list, primary_monitor_attributes, monitor_frames);
4968
4969 for (i = 0; i < n_monitors; i++)
4970 {
4971 Lisp_Object geometry, workarea, name, attributes = Qnil;
4972 HDC hdc;
4973 int width_mm, height_mm;
4974 struct MONITOR_INFO_EX mi;
4975
4976 mi.cbSize = sizeof (mi);
4977 if (!get_monitor_info_fn (monitors[i], (struct MONITOR_INFO *) &mi))
4978 continue;
4979
4980 hdc = CreateDCA ("DISPLAY", mi.szDevice, NULL, NULL);
4981 if (hdc == NULL)
4982 continue;
4983 width_mm = GetDeviceCaps (hdc, HORZSIZE);
4984 height_mm = GetDeviceCaps (hdc, VERTSIZE);
4985 DeleteDC (hdc);
4986
4987 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4988 attributes);
4989
4990 name = DECODE_SYSTEM (make_unibyte_string (mi.szDevice,
4991 strlen (mi.szDevice)));
4992 attributes = Fcons (Fcons (Qname, name), attributes);
4993
4994 attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
4995 attributes);
4996
4997 workarea = list4i (mi.rcWork.left, mi.rcWork.top,
4998 mi.rcWork.right - mi.rcWork.left,
4999 mi.rcWork.bottom - mi.rcWork.top);
5000 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5001
5002 geometry = list4i (mi.rcMonitor.left, mi.rcMonitor.top,
5003 mi.rcMonitor.right - mi.rcMonitor.left,
5004 mi.rcMonitor.bottom - mi.rcMonitor.top);
5005 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5006
5007 if (mi.dwFlags & MONITORINFOF_PRIMARY)
5008 primary_monitor_attributes = attributes;
5009 else
5010 attributes_list = Fcons (attributes, attributes_list);
5011 }
5012
5013 if (!NILP (primary_monitor_attributes))
5014 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5015
5016 UNGCPRO;
5017
5018 xfree (monitors);
5019
5020 return attributes_list;
5021}
5022
5023static Lisp_Object
5024w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo)
5025{
5026 Lisp_Object geometry, workarea, frames, rest, frame, attributes = Qnil;
5027 HDC hdc;
5028 double mm_per_pixel;
5029 int pixel_width, pixel_height, width_mm, height_mm;
5030 RECT workarea_rect;
5031
5032 /* Fallback: treat (possibly) multiple physical monitors as if they
5033 formed a single monitor as a whole. This should provide a
5034 consistent result at least on single monitor environments. */
5035 attributes = Fcons (Fcons (Qname, build_string ("combined screen")),
5036 attributes);
5037
5038 frames = Qnil;
5039 FOR_EACH_FRAME (rest, frame)
5040 {
5041 struct frame *f = XFRAME (frame);
5042
5043 if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
5044 frames = Fcons (frame, frames);
5045 }
5046 attributes = Fcons (Fcons (Qframes, frames), attributes);
5047
5048 pixel_width = x_display_pixel_width (dpyinfo);
5049 pixel_height = x_display_pixel_height (dpyinfo);
5050
5051 hdc = GetDC (NULL);
5052 mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
5053 / GetDeviceCaps (hdc, HORZRES));
5054 width_mm = pixel_width * mm_per_pixel + 0.5;
5055 mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
5056 / GetDeviceCaps (hdc, VERTRES));
5057 height_mm = pixel_height * mm_per_pixel + 0.5;
5058 ReleaseDC (NULL, hdc);
5059 attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
5060 attributes);
5061
5062 /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but
5063 we don't care. */
5064 geometry = list4i (GetSystemMetrics (SM_XVIRTUALSCREEN),
5065 GetSystemMetrics (SM_YVIRTUALSCREEN),
5066 pixel_width, pixel_height);
5067 if (SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0))
5068 workarea = list4i (workarea_rect.left, workarea_rect.top,
5069 workarea_rect.right - workarea_rect.left,
5070 workarea_rect.bottom - workarea_rect.top);
5071 else
5072 workarea = geometry;
5073 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5074
5075 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5076
5077 return list1 (attributes);
5078}
5079
5080DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list,
5081 Sw32_display_monitor_attributes_list,
5082 0, 1, 0,
5083 doc: /* Return a list of physical monitor attributes on the W32 display DISPLAY.
5084
5085The optional argument DISPLAY specifies which display to ask about.
5086DISPLAY should be either a frame or a display name (a string).
5087If omitted or nil, that stands for the selected frame's display.
5088
5089Internal use only, use `display-monitor-attributes-list' instead. */)
5090 (Lisp_Object display)
5091{
5092 struct w32_display_info *dpyinfo = check_x_display_info (display);
5093 Lisp_Object attributes_list;
5094
5095 block_input ();
5096 attributes_list = w32_display_monitor_attributes_list ();
5097 if (NILP (attributes_list))
5098 attributes_list = w32_display_monitor_attributes_list_fallback (dpyinfo);
5099 unblock_input ();
5100
5101 return attributes_list;
5102}
5103
4868DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0, 5104DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
4869 doc: /* Set the sound generated when the bell is rung. 5105 doc: /* Set the sound generated when the bell is rung.
4870SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent 5106SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
@@ -7357,6 +7593,10 @@ syms_of_w32fns (void)
7357 DEFSYM (Qcontrol, "control"); 7593 DEFSYM (Qcontrol, "control");
7358 DEFSYM (Qshift, "shift"); 7594 DEFSYM (Qshift, "shift");
7359 DEFSYM (Qfont_param, "font-parameter"); 7595 DEFSYM (Qfont_param, "font-parameter");
7596 DEFSYM (Qgeometry, "geometry");
7597 DEFSYM (Qworkarea, "workarea");
7598 DEFSYM (Qmm_size, "mm-size");
7599 DEFSYM (Qframes, "frames");
7360 /* This is the end of symbol initialization. */ 7600 /* This is the end of symbol initialization. */
7361 7601
7362 7602
@@ -7646,6 +7886,7 @@ only be necessary if the default setting causes problems. */);
7646 7886
7647 defsubr (&Sw32_define_rgb_color); 7887 defsubr (&Sw32_define_rgb_color);
7648 defsubr (&Sw32_default_color_map); 7888 defsubr (&Sw32_default_color_map);
7889 defsubr (&Sw32_display_monitor_attributes_list);
7649 defsubr (&Sw32_send_sys_command); 7890 defsubr (&Sw32_send_sys_command);
7650 defsubr (&Sw32_shell_execute); 7891 defsubr (&Sw32_shell_execute);
7651 defsubr (&Sw32_register_hot_key); 7892 defsubr (&Sw32_register_hot_key);
@@ -7707,6 +7948,8 @@ globals_of_w32fns (void)
7707 GetProcAddress (user32_lib, "GetMonitorInfoA"); 7948 GetProcAddress (user32_lib, "GetMonitorInfoA");
7708 monitor_from_window_fn = (MonitorFromWindow_Proc) 7949 monitor_from_window_fn = (MonitorFromWindow_Proc)
7709 GetProcAddress (user32_lib, "MonitorFromWindow"); 7950 GetProcAddress (user32_lib, "MonitorFromWindow");
7951 enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
7952 GetProcAddress (user32_lib, "EnumDisplayMonitors");
7710 7953
7711 { 7954 {
7712 HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); 7955 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
diff --git a/src/w32term.c b/src/w32term.c
index d3174c65bf0..fcd5886d5c9 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -143,6 +143,15 @@ BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
143#define WS_EX_LAYERED 0x80000 143#define WS_EX_LAYERED 0x80000
144#endif 144#endif
145 145
146/* SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN are not defined on 95 and
147 NT4. */
148#ifndef SM_CXVIRTUALSCREEN
149#define SM_CXVIRTUALSCREEN 78
150#endif
151#ifndef SM_CYVIRTUALSCREEN
152#define SM_CYVIRTUALSCREEN 79
153#endif
154
146/* This is a frame waiting to be autoraised, within w32_read_socket. */ 155/* This is a frame waiting to be autoraised, within w32_read_socket. */
147struct frame *pending_autoraise_frame; 156struct frame *pending_autoraise_frame;
148 157
@@ -519,18 +528,24 @@ x_set_frame_alpha (struct frame *f)
519int 528int
520x_display_pixel_height (struct w32_display_info *dpyinfo) 529x_display_pixel_height (struct w32_display_info *dpyinfo)
521{ 530{
522 HDC dc = GetDC (NULL); 531 int pixels = GetSystemMetrics (SM_CYVIRTUALSCREEN);
523 int pixels = GetDeviceCaps (dc, VERTRES); 532
524 ReleaseDC (NULL, dc); 533 if (pixels == 0)
534 /* Fallback for Windows 95 or NT 4.0. */
535 pixels = GetSystemMetrics (SM_CYSCREEN);
536
525 return pixels; 537 return pixels;
526} 538}
527 539
528int 540int
529x_display_pixel_width (struct w32_display_info *dpyinfo) 541x_display_pixel_width (struct w32_display_info *dpyinfo)
530{ 542{
531 HDC dc = GetDC (NULL); 543 int pixels = GetSystemMetrics (SM_CXVIRTUALSCREEN);
532 int pixels = GetDeviceCaps (dc, HORZRES); 544
533 ReleaseDC (NULL, dc); 545 if (pixels == 0)
546 /* Fallback for Windows 95 or NT 4.0. */
547 pixels = GetSystemMetrics (SM_CXSCREEN);
548
534 return pixels; 549 return pixels;
535} 550}
536 551