Подробности

[В начало]

Проблема в реализации № D0129

Краткое описание

Поведение функции gdk_screen_get_monitor_at_window() не соответствует требованиям стандарта LSB 3.2

Подробное описание

В документации GDK-2.8.2, на которую ссылается стандарт LSB 3.2, функция gdk_screen_get_monitor_at_window должна вернуть номер монитора, в котором находится большая часть окна. В действительности gdk_screen_get_monitor_at_window возвращает номер монитора, не соответствующий ожидаемому.

Причина этого, по нашему мнению, заключается в следующем фрагменте исходного кода функции:

gint 
gdk_screen_get_monitor_at_window (GdkScreen *screen, GdkWindow *window)

{
   ...
   gdk_window_get_geometry (window, &win_rect.x, &win_rect.y,&иin_rect.width, 
&win_rect.height, NULL);
   gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
   ...
   gdk_rectangle_intersect (&win_rect, &tmp_monitor, &intersect);
   ...
}
Проблема здесь в том, что в вызове функции gdk_window_get_origin используется те же самые координаты win_rect, которые изменяются после вызова gdk_window_get_origin.

Раздел стандарта

Linux Standard Base Desktop Specification 3.2. Chapter 15. Libraries. 15.21.1.1. Interfaces for GTK Drawing toolkit., который ссылается на http://www.gtk.org/api/2.6/gdk/GdkScreen.html#id2663323

Пример

#include <gdk/gdk.h>
#include <glib.h>
#include <stdio.h>

int getMonitorWidth(GdkScreen *screen, int monitorNum) 
{
	GdkRectangle monitor;
   	gdk_screen_get_monitor_geometry (screen, monitorNum, &monitor);
   	return monitor.width;
}

int main (int argc, char **argv)
{
#define X_LOCATION		getMonitorWidth(screen, 0) - 10
#define Y_LOCATION		10
#define WIDTH			200
#define HEIGHT			200
#define EXPECTED 		1

	GdkWindow *window = NULL;
	GdkWindowAttr attr;
	GdkScreen *screen = NULL;
	
	gdk_init(&argc, &argv);
	
	screen = gdk_screen_get_default();
	
	gint num_monitors = gdk_screen_get_n_monitors (screen);
	
	attr.title = "NEW_WINDOW";
	attr.x = X_LOCATION;
	attr.y = Y_LOCATION;
	attr.width = WIDTH;
	attr.height = HEIGHT;
	attr.wclass = GDK_INPUT_OUTPUT;
	attr.window_type = GDK_WINDOW_TOPLEVEL;

	window = gdk_window_new(NULL, &attr, GDK_WA_X | GDK_WA_Y |GDK_WA_TITLE);
	if (window == NULL)
	{
		printf("The gdk_window_new function returned NULL, unable to create GdkWindow.\n");
		return 0;
	}
	gdk_window_show(window);

	gint monitorNum = gdk_screen_get_monitor_at_window(screen, window);
        printf("monitorNum = %d", monitorNum);
        printf("Expected = %d, received = %d", EXPECTED, monitorNum);
   	
	if(window != NULL)
	{
		gdk_window_destroy(window);
	}
 	return 0;
}

Способы устранения

Следует вызывать gdk_window_get_origin с другими параметрами, скажем, orig_rect.

@@ -1,13 +1,13 @@
 gint gsk_screen_get_monitor_at_window (GdkScreen *screen, GdkWindow *window)
 {
        gint num_monitors, i, area = 0, screen_num = -1;
-       GdkRectangle win_rect;
+       GdkRectangle win_rect, orig_rect;
        g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);

        gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width,
                            &win_rect.height, NULL);

-       gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
+       gdk_window_get_origin (window, &orig_rect.x, &orig_rect.y);

        num_monitors = gdk_screen_get_n_monitors (screen);

@@ -27,6 +27,6 @@
        if (screen_num >= 0)
        return screen_num;
        else
-       return get_nearest_monitor (screen, win_rect.x + win_rect.width / 2,
-                                win_rect.y + win_rect.height / 2);
+       return get_nearest_monitor (screen, orig_rect.x + win_rect.width / 2,
+                                orig_rect.y + win_rect.height / 2);
 }

Компонент

gtk+ 2.19.x or early

Окружение

Прочее

The problem was discovered under the system with two monitors connected to each other horizontally.

Принято

Gnome Bugzilla, 583879

[В начало]