From: Yuuki Harano Date: Sun, 3 Jan 2021 06:07:37 +0000 (+0900) Subject: Fix pgtk-display-monitor-attributes-list to return physical pixel sizes. X-Git-Tag: emacs-29.0.90~3746 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=91d450d1fbe78717f34f4c28789d3f4c6ecd6061;p=emacs.git Fix pgtk-display-monitor-attributes-list to return physical pixel sizes. * src/pgtkfns.c (Fpgtk_display_monitor_attributes_list): Re-port it. --- diff --git a/src/pgtkfns.c b/src/pgtkfns.c index cf84163fee0..f52dab6dbe8 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2383,109 +2383,108 @@ each physical monitor, use `display-monitor-attributes-list'. */) return make_fixnum (x_display_pixel_height (dpyinfo)); } -DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, Spgtk_display_monitor_attributes_list, 0, 1, 0, +DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, + Spgtk_display_monitor_attributes_list, + 0, 1, 0, doc: /* Return a list of physical monitor attributes on the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. +In addition to the standard attribute keys listed in +`display-monitor-attributes-list', the following keys are contained in +the attributes: + + source -- String describing the source from which multi-monitor + information is obtained, \"Gdk\" + Internal use only, use `display-monitor-attributes-list' instead. */) (Lisp_Object terminal) { - struct terminal *term = decode_live_terminal (terminal); struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor **gmons; - int i, n_monitors, primary_index; - struct MonitorInfo *monitors; - Lisp_Object monitor_frames = Qnil; - Lisp_Object frame = Qnil, rest = Qnil; - Lisp_Object rv = Qnil; + Lisp_Object attributes_list = Qnil; - if (term->type != output_pgtk) - return Qnil; + GdkDisplay *gdpy; + gint primary_monitor = 0, n_monitors, i; + Lisp_Object monitor_frames, rest, frame; + static const char *source = "Gdk"; + struct MonitorInfo *monitors; + block_input (); + gdpy = dpyinfo->gdpy; n_monitors = gdk_display_get_n_monitors (gdpy); - if (n_monitors == 0) - return Qnil; - - gmons = xmalloc (sizeof *gmons * n_monitors); - for (i = 0; i < n_monitors; i++) - gmons[i] = gdk_display_get_monitor (gdpy, i); - + monitor_frames = make_nil_vector (n_monitors); monitors = xzalloc (n_monitors * sizeof *monitors); - for (i = 0; i < n_monitors; i++) - { - struct MonitorInfo *mon = &monitors[i]; - GdkMonitor *gmon = gmons[i]; - if (gmon != NULL) - { - GdkRectangle geom; - gdk_monitor_get_geometry (gmon, &geom); - mon->geom.x = geom.x; - mon->geom.y = geom.y; - mon->geom.width = geom.width; - mon->geom.height = geom.height; - - gdk_monitor_get_workarea (gmon, &geom); - mon->work.x = geom.x; - mon->work.y = geom.y; - mon->work.width = geom.width; - mon->work.height = geom.height; - - mon->mm_width = gdk_monitor_get_width_mm (gmon); - mon->mm_height = gdk_monitor_get_height_mm (gmon); - - mon->name = xstrdup (gdk_monitor_get_model (gmon)); - } - } - monitor_frames = Fmake_vector (make_fixnum (n_monitors), Qnil); FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); - - if (FRAME_PGTK_P (f)) - { - GtkWidget *widget = FRAME_GTK_WIDGET (f); - GdkMonitor *gmon = - gdk_display_get_monitor_at_window (gdpy, - gtk_widget_get_window (widget)); - - if (gmon != NULL) - { - for (i = 0; i < n_monitors; i++) - { - if (gmons[i] == gmon) - { - ASET (monitor_frames, i, - Fcons (frame, AREF (monitor_frames, i))); - break; - } - } - } - } - } - - primary_index = -1; - for (i = 0; i < n_monitors; i++) { - if (gmons[i] != NULL && gdk_monitor_is_primary (gmons[i])) + struct frame *f = XFRAME (frame); + + if (FRAME_PGTK_P (f) + && FRAME_DISPLAY_INFO (f) == dpyinfo + && !FRAME_TOOLTIP_P (f)) { - primary_index = i; - break; + GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + + for (i = 0; i < n_monitors; i++) + if (gdk_display_get_monitor_at_window (gdpy, gwin) + == gdk_display_get_monitor (gdpy, i)) + break; + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); } } - rv = - make_monitor_attribute_list (monitors, n_monitors, primary_index, - monitor_frames, "Gdk"); - + for (i = 0; i < n_monitors; ++i) + { + gint width_mm, height_mm; + GdkRectangle rec, work; + struct MonitorInfo *mi = &monitors[i]; + int scale = 1; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + if (gdk_monitor_is_primary (monitor)) + primary_monitor = i; + gdk_monitor_get_geometry (monitor, &rec); + + width_mm = gdk_monitor_get_width_mm (monitor); + height_mm = gdk_monitor_get_height_mm (monitor); + gdk_monitor_get_workarea (monitor, &work); + + /* GTK returns scaled sizes for the workareas. */ + scale = gdk_monitor_get_scale_factor (monitor); + rec.x *= scale; + rec.y *= scale; + rec.width *= scale; + rec.height *= scale; + work.x *= scale; + work.y *= scale; + work.width *= scale; + work.height *= scale; + + mi->geom.x = rec.x; + mi->geom.y = rec.y; + mi->geom.width = rec.width; + mi->geom.height = rec.height; + mi->work.x = work.x; + mi->work.y = work.y; + mi->work.width = work.width; + mi->work.height = work.height; + mi->mm_width = width_mm; + mi->mm_height = height_mm; + + dupstring (&mi->name, (gdk_monitor_get_model (monitor))); + } + + attributes_list = make_monitor_attribute_list (monitors, + n_monitors, + primary_monitor, + monitor_frames, + source); free_monitors (monitors, n_monitors); - xfree (gmons); + unblock_input (); - return rv; + return attributes_list; }