Compare commits
78 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d5d95b2834 | ||
![]() |
659b8ed471 | ||
![]() |
94bce5a00f | ||
![]() |
91b7dedf36 | ||
![]() |
aa1c819941 | ||
![]() |
be7e994abd | ||
![]() |
6c05eb583e | ||
![]() |
5547c98f97 | ||
![]() |
ea4979e182 | ||
![]() |
8da5761ffc | ||
![]() |
aea71fbd01 | ||
![]() |
b55f792302 | ||
![]() |
dd060d78ce | ||
![]() |
3fe281ada9 | ||
![]() |
f041b35b9b | ||
![]() |
afa58746ea | ||
![]() |
6dbec6f81b | ||
![]() |
2cbaa6660c | ||
![]() |
d74b0d5be8 | ||
![]() |
6b82f61dba | ||
![]() |
4c6866741d | ||
![]() |
84baf4e181 | ||
![]() |
3962f1d982 | ||
![]() |
414be07a69 | ||
![]() |
7f3ada7831 | ||
![]() |
12771a555a | ||
![]() |
92d6a69153 | ||
![]() |
734402e14d | ||
![]() |
5d360a9bce | ||
![]() |
f8cf5e373c | ||
![]() |
8df3fa4e67 | ||
![]() |
bbf2b4e60e | ||
![]() |
bb4dcd62ec | ||
![]() |
2345b9c6ad | ||
![]() |
af7cc87bfa | ||
![]() |
af3b599cbb | ||
![]() |
0e73ceb4bd | ||
![]() |
82a7060cdb | ||
![]() |
09120132ef | ||
![]() |
cdac4d0e92 | ||
![]() |
6aead0c67c | ||
![]() |
d593a61b39 | ||
![]() |
9747277b7e | ||
![]() |
989f9630a4 | ||
![]() |
daa15d94fd | ||
![]() |
999b99a077 | ||
![]() |
fd0b366a96 | ||
![]() |
320e2d452f | ||
![]() |
4d5dd01b7d | ||
![]() |
103c88bd72 | ||
![]() |
64cf87cfe1 | ||
![]() |
9f65edd4f5 | ||
![]() |
ea2496c80a | ||
![]() |
0c30ceddbe | ||
![]() |
5c9846c53a | ||
![]() |
2a8563ab23 | ||
![]() |
6a77d9722a | ||
![]() |
ef296031cb | ||
![]() |
e2d6028924 | ||
![]() |
4d80a4cc31 | ||
![]() |
4a968c3b4e | ||
![]() |
ccb7833e99 | ||
![]() |
b449ba942a | ||
![]() |
f53eea2c1c | ||
![]() |
b62db404ee | ||
![]() |
90a28e7b1c | ||
![]() |
8d51a9db5b | ||
![]() |
b39c00f344 | ||
![]() |
83ce71c3bf | ||
![]() |
f9d869a3dd | ||
![]() |
0b0ce4193f | ||
![]() |
719d8bd0c7 | ||
![]() |
4fc1811c15 | ||
![]() |
4b5f5abb4f | ||
![]() |
95ad52ba58 | ||
![]() |
dac30a222e | ||
![]() |
7d1b593fbd | ||
![]() |
d6a7559750 |
25
NEWS
25
NEWS
@@ -1,3 +1,28 @@
|
||||
3.17.3
|
||||
======
|
||||
* Add X11/wayland clipboard interaction [Carlos; #738312]
|
||||
* Support VM monitor layout hints on wayland [Thomas; #750363]
|
||||
* Misc. bug fixes [Rui, Jonas, Olivier, Carlos, Ting-Wei, Peter, Florian;
|
||||
#749994, #750256, #749716, #748705, #750552, #751036, #750007, #751136,
|
||||
#750552, #751471, #751715, #750680]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Dave Airlie, Cosimo Cecchi, Olivier Fourdan, Carlos Garnacho,
|
||||
Thomas Hellstrom, Peter Hutterer, Ting-Wei Lan, Jasper Lievisse Adriaanse,
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Marek Černocký [cs], Christian Kirbach [de], Pedro Albuquerque [pt]
|
||||
|
||||
3.17.2
|
||||
======
|
||||
* Honor default value for click method setting [Rui; #746290]
|
||||
* Add X11/wayland clipboard interoperation [Carlos; #738312]
|
||||
* Misc. bug fixes [Rui; #749076, #749711]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Rui Matos, Jasper St. Pierre
|
||||
|
||||
3.17.1
|
||||
======
|
||||
* Add public method to get neighboring monitor [Florian; #633994]
|
||||
|
17
configure.ac
17
configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [17])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_micro_version], [3])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -52,19 +52,6 @@ PKG_PROG_PKG_CONFIG([0.21])
|
||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||
AM_PATH_GLIB_2_0()
|
||||
|
||||
#### Integer sizes
|
||||
|
||||
AC_CHECK_SIZEOF(char)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(void *)
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
AC_CHECK_SIZEOF(__int64)
|
||||
|
||||
## byte order
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
@@ -284,6 +271,8 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
|
||||
|
||||
if test "x$found_randr" = "xyes"; then
|
||||
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
|
||||
PKG_CHECK_EXISTS([xrandr >= 1.5.0],
|
||||
AC_DEFINE([HAVE_XRANDR15],[1],[Define if you have support for XRandR 1.5 or greater]))
|
||||
fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
|
66
po/cs.po
66
po/cs.po
@@ -30,91 +30,91 @@ msgstr "Navigace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:2
|
||||
msgid "Move window to workspace 1"
|
||||
msgstr "Přesunout okno na plochu 1"
|
||||
msgstr "Přesunout okno na pracovní plochu 1"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:3
|
||||
msgid "Move window to workspace 2"
|
||||
msgstr "Přesunout okno na plochu 2"
|
||||
msgstr "Přesunout okno na pracovní plochu 2"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:4
|
||||
msgid "Move window to workspace 3"
|
||||
msgstr "Přesunout okno na plochu 3"
|
||||
msgstr "Přesunout okno na pracovní plochu 3"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:5
|
||||
msgid "Move window to workspace 4"
|
||||
msgstr "Přesunout okno na plochu 4"
|
||||
msgstr "Přesunout okno na pracovní plochu 4"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:6
|
||||
msgid "Move window to last workspace"
|
||||
msgstr "Přesunout okno na poslední plochu"
|
||||
msgstr "Přesunout okno na poslední pracovní plochu"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:7
|
||||
msgid "Move window one workspace to the left"
|
||||
msgstr "Přesunout okno o plochu doleva"
|
||||
msgstr "Přesunout okno o jednu pracovní plochu doleva"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:8
|
||||
msgid "Move window one workspace to the right"
|
||||
msgstr "Přesunout okno o plochu doprava"
|
||||
msgstr "Přesunout okno o jednu pracovní plochu doprava"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:9
|
||||
msgid "Move window one workspace up"
|
||||
msgstr "Přesunout okno o plochu nahoru"
|
||||
msgstr "Přesunout okno o jednu pracovní plochu nahoru"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:10
|
||||
msgid "Move window one workspace down"
|
||||
msgstr "Přesunout okno o plochu dolů"
|
||||
msgstr "Přesunout okno o jednu pracovní plochu dolů"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:11
|
||||
msgid "Move window one monitor to the left"
|
||||
msgstr "Přesunout okno o monitor doleva"
|
||||
msgstr "Přesunout okno o jeden monitor doleva"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:12
|
||||
msgid "Move window one monitor to the right"
|
||||
msgstr "Přesunout okno o monitor doprava"
|
||||
msgstr "Přesunout okno o jeden monitor doprava"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:13
|
||||
msgid "Move window one monitor up"
|
||||
msgstr "Přesunout okno o monitor nahoru"
|
||||
msgstr "Přesunout okno o jeden monitor nahoru"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:14
|
||||
msgid "Move window one monitor down"
|
||||
msgstr "Přesunout okno o monitor dolů"
|
||||
msgstr "Přesunout okno o jeden monitor dolů"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:15
|
||||
msgid "Switch applications"
|
||||
msgstr "Přepnout mezi aplikacemi"
|
||||
msgstr "Přepnout do jiné aplikace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:16
|
||||
msgid "Switch to previous application"
|
||||
msgstr "Přepnout na předchozí aplikaci"
|
||||
msgstr "Přepnout do předchozí aplikaci"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:17
|
||||
msgid "Switch windows"
|
||||
msgstr "Přepnout mezi okny"
|
||||
msgstr "Přepnout do jiného okna"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:18
|
||||
msgid "Switch to previous window"
|
||||
msgstr "Přepnout na předchozí okno"
|
||||
msgstr "Přepnout do minulého okna"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:19
|
||||
msgid "Switch windows of an application"
|
||||
msgstr "Přepnout mezi okny aplikace"
|
||||
msgstr "Přepnout do jiného okna aplikace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:20
|
||||
msgid "Switch to previous window of an application"
|
||||
msgstr "Přepnout na předchozí okno aplikace"
|
||||
msgstr "Přepnout do předchozího okna aplikace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:21
|
||||
msgid "Switch system controls"
|
||||
msgstr "Přepnout mezi systémovými ovládacími prvky"
|
||||
msgstr "Přepnout na systémový ovládací prvek"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:22
|
||||
msgid "Switch to previous system control"
|
||||
msgstr "Přepnout na předchozí systémové ovládací prvky"
|
||||
msgstr "Přepnout na minulý systémový ovládací prvek"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:23
|
||||
msgid "Switch windows directly"
|
||||
msgstr "Přepnout přímo mezi okny"
|
||||
msgstr "Přepnout do minulého okna"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:24
|
||||
msgid "Switch directly to previous window"
|
||||
@@ -122,15 +122,15 @@ msgstr "Přepnout přímo na předchozí okno"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:25
|
||||
msgid "Switch windows of an app directly"
|
||||
msgstr "Přepnout přímo mezi okny aplikace"
|
||||
msgstr "Přepnout do jiného okna aplikace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:26
|
||||
msgid "Switch directly to previous window of an app"
|
||||
msgstr "Přepnout přímo na předchozí okno aplikace"
|
||||
msgstr "Přepnout do předchozího okna aplikace"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:27
|
||||
msgid "Switch system controls directly"
|
||||
msgstr "Přepnout přímo mezi systémovými ovládacími prvky"
|
||||
msgstr "Přepnout na minulý systémový ovládací prvek"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:28
|
||||
msgid "Switch directly to previous system control"
|
||||
@@ -198,7 +198,7 @@ msgstr "Aktivovat nabídku okna"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:3
|
||||
msgid "Toggle fullscreen mode"
|
||||
msgstr "Přepnout režim na celou obrazovku"
|
||||
msgstr "Přepnout režim celé obrazovky"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:4
|
||||
msgid "Toggle maximization state"
|
||||
@@ -210,7 +210,7 @@ msgstr "Maximalizovat okno"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:6
|
||||
msgid "Restore window"
|
||||
msgstr "Obnovit okno"
|
||||
msgstr "Obnovit velikost okna"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:7
|
||||
msgid "Toggle shaded state"
|
||||
@@ -234,20 +234,20 @@ msgstr "Změnit velikost okna"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:12
|
||||
msgid "Toggle window on all workspaces or one"
|
||||
msgstr "Přepnout výskyt okna na všech plochách nebo jen na jedné"
|
||||
msgstr "Přepnout okno na všechny/jednu pracovní plochu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:13
|
||||
msgid "Raise window if covered, otherwise lower it"
|
||||
msgstr ""
|
||||
"Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
|
||||
"Když je okno zakryté vynést jej do popředí, jinak odsunout do pozadí"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:14
|
||||
msgid "Raise window above other windows"
|
||||
msgstr "Přenést okno do popředí nad ostatní okna"
|
||||
msgstr "Vynést okno do popředí nad ostatní okna"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:15
|
||||
msgid "Lower window below other windows"
|
||||
msgstr "Odsunout okno do pozadí pod ostatní okna"
|
||||
msgstr "Odsunout okno do pozadí za ostatní okna"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:16
|
||||
msgid "Maximize window vertically"
|
||||
@@ -259,11 +259,11 @@ msgstr "Maximalizovat okno vodorovně"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:18
|
||||
msgid "View split on left"
|
||||
msgstr "Zobrazit rozdělení nalevo"
|
||||
msgstr "Rozdělit okno přes levou půlku obrazovky"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:19
|
||||
msgid "View split on right"
|
||||
msgstr "Zobrazit rozdělení napravo"
|
||||
msgstr "Rozdělit okno přes pravou půlku obrazovky"
|
||||
|
||||
#: ../data/mutter.desktop.in.h:1
|
||||
msgid "Mutter"
|
||||
|
@@ -41,9 +41,6 @@ endif
|
||||
# Some random test programs for bits of the code
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS+=testboxes testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
noinst_PROGRAMS += testboxes
|
||||
|
@@ -210,8 +210,6 @@ libmutter_la_SOURCES = \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/atomnames.h \
|
||||
x11/events.c \
|
||||
x11/events.h \
|
||||
@@ -243,6 +241,8 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
wayland/meta-xwayland.h \
|
||||
wayland/meta-xwayland-selection.c \
|
||||
wayland/meta-xwayland-selection-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-wayland-buffer.c \
|
||||
wayland/meta-wayland-buffer.h \
|
||||
@@ -250,6 +250,7 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-region.h \
|
||||
wayland/meta-wayland-data-device.c \
|
||||
wayland/meta-wayland-data-device.h \
|
||||
wayland/meta-wayland-data-device-private.h \
|
||||
wayland/meta-wayland-keyboard.c \
|
||||
wayland/meta-wayland-keyboard.h \
|
||||
wayland/meta-wayland-pointer.c \
|
||||
|
@@ -886,14 +886,14 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
GPtrArray *crtcs, *outputs;
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GPtrArray) crtcs = NULL;
|
||||
g_autoptr(GPtrArray) outputs = NULL;
|
||||
|
||||
crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
|
||||
outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
|
||||
|
||||
if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
meta_monitor_manager_apply_configuration (manager,
|
||||
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
|
||||
@@ -905,12 +905,7 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
* inside turn_off_laptop_display / apply_configuration_with_lid */
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1079,12 +1074,12 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
* which are internal monitors), or failing that, the one with the
|
||||
* best resolution
|
||||
*/
|
||||
static MetaOutput *
|
||||
static int
|
||||
find_primary_output (MetaOutput *outputs,
|
||||
unsigned n_outputs)
|
||||
{
|
||||
unsigned i;
|
||||
MetaOutput *best;
|
||||
int best;
|
||||
int best_width, best_height;
|
||||
|
||||
g_assert (n_outputs >= 1);
|
||||
@@ -1092,23 +1087,23 @@ find_primary_output (MetaOutput *outputs,
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].is_primary)
|
||||
return &outputs[i];
|
||||
return i;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (output_is_laptop (&outputs[i]))
|
||||
return &outputs[i];
|
||||
return i;
|
||||
}
|
||||
|
||||
best = NULL;
|
||||
best = -1;
|
||||
best_width = 0; best_height = 0;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].preferred_mode->width * outputs[i].preferred_mode->height >
|
||||
best_width * best_height)
|
||||
{
|
||||
best = &outputs[i];
|
||||
best = i;
|
||||
best_width = outputs[i].preferred_mode->width;
|
||||
best_height = outputs[i].preferred_mode->height;
|
||||
}
|
||||
@@ -1146,7 +1141,7 @@ make_suggested_config (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
unsigned int i;
|
||||
MetaOutput *primary;
|
||||
int primary;
|
||||
GList *region = NULL;
|
||||
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
@@ -1154,7 +1149,7 @@ make_suggested_config (MetaMonitorConfig *self,
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
gboolean is_primary = ((int)i == primary);
|
||||
|
||||
if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
|
||||
return FALSE;
|
||||
@@ -1181,6 +1176,81 @@ make_suggested_config (MetaMonitorConfig *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
config_one_untiled_output (MetaOutput *outputs,
|
||||
MetaConfiguration *config,
|
||||
int idx, gboolean is_primary,
|
||||
int *x, unsigned long *output_configured_bitmap)
|
||||
{
|
||||
MetaOutput *output = &outputs[idx];
|
||||
|
||||
if (*output_configured_bitmap & (1 << idx))
|
||||
return;
|
||||
|
||||
init_config_from_preferred_mode (&config->outputs[idx], output);
|
||||
config->outputs[idx].is_primary = is_primary;
|
||||
config->outputs[idx].rect.x = *x;
|
||||
*x += config->outputs[idx].rect.width;
|
||||
*output_configured_bitmap |= (1 << idx);
|
||||
}
|
||||
|
||||
static void
|
||||
config_one_tiled_group (MetaOutput *outputs,
|
||||
MetaConfiguration *config,
|
||||
int base_idx, gboolean is_primary,
|
||||
int n_outputs,
|
||||
int *x, unsigned long *output_configured_bitmap)
|
||||
{
|
||||
guint32 num_h_tile, num_v_tile, ht, vt;
|
||||
int j;
|
||||
int cur_x, cur_y, addx = 0;
|
||||
|
||||
if (*output_configured_bitmap & (1 << base_idx))
|
||||
return;
|
||||
|
||||
if (outputs[base_idx].tile_info.group_id == 0)
|
||||
return;
|
||||
|
||||
cur_x = cur_y = 0;
|
||||
num_h_tile = outputs[base_idx].tile_info.max_h_tiles;
|
||||
num_v_tile = outputs[base_idx].tile_info.max_v_tiles;
|
||||
|
||||
/* iterate over horizontal tiles */
|
||||
cur_x = *x;
|
||||
for (ht = 0; ht < num_h_tile; ht++)
|
||||
{
|
||||
cur_y = 0;
|
||||
addx = 0;
|
||||
for (vt = 0; vt < num_v_tile; vt++)
|
||||
{
|
||||
for (j = 0; j < n_outputs; j++)
|
||||
{
|
||||
if (outputs[j].tile_info.group_id != outputs[base_idx].tile_info.group_id)
|
||||
continue;
|
||||
|
||||
if (outputs[j].tile_info.loc_h_tile != ht ||
|
||||
outputs[j].tile_info.loc_v_tile != vt)
|
||||
continue;
|
||||
|
||||
if (ht == 0 && vt == 0 && is_primary)
|
||||
config->outputs[j].is_primary = TRUE;
|
||||
|
||||
init_config_from_preferred_mode (&config->outputs[j], &outputs[j]);
|
||||
config->outputs[j].rect.x = cur_x;
|
||||
config->outputs[j].rect.y = cur_y;
|
||||
|
||||
*output_configured_bitmap |= (1 << j);
|
||||
cur_y += outputs[j].tile_info.tile_h;
|
||||
if (vt == 0)
|
||||
addx += outputs[j].tile_info.tile_w;
|
||||
}
|
||||
}
|
||||
cur_x += addx;
|
||||
}
|
||||
*x = cur_x;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
make_linear_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
@@ -1189,31 +1259,41 @@ make_linear_config (MetaMonitorConfig *self,
|
||||
int max_height,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
MetaOutput *primary;
|
||||
unsigned long output_configured_bitmap = 0;
|
||||
unsigned i;
|
||||
int x;
|
||||
int primary;
|
||||
|
||||
g_return_if_fail (config != NULL);
|
||||
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
x = primary->preferred_mode->width;
|
||||
x = 0;
|
||||
/* set the primary up first at 0 */
|
||||
if (outputs[primary].tile_info.group_id)
|
||||
{
|
||||
config_one_tiled_group (outputs, config, primary, TRUE, n_outputs,
|
||||
&x, &output_configured_bitmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
config_one_untiled_output (outputs, config, primary, TRUE,
|
||||
&x, &output_configured_bitmap);
|
||||
}
|
||||
|
||||
/* then add other tiled monitors */
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
config_one_tiled_group (outputs, config, i, FALSE, n_outputs,
|
||||
&x, &output_configured_bitmap);
|
||||
}
|
||||
|
||||
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
|
||||
config->outputs[i].is_primary = is_primary;
|
||||
/* then add remaining monitors */
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
config_one_untiled_output (outputs, config, i, FALSE,
|
||||
&x, &output_configured_bitmap);
|
||||
|
||||
if (is_primary)
|
||||
{
|
||||
config->outputs[i].rect.x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
config->outputs[i].rect.x = x;
|
||||
x += config->outputs[i].rect.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,7 +1417,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
unsigned n_outputs)
|
||||
{
|
||||
MetaConfiguration *config;
|
||||
MetaOutput *primary;
|
||||
int primary;
|
||||
unsigned i;
|
||||
|
||||
/* Check that we have at least one active output */
|
||||
@@ -1355,7 +1435,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
gboolean is_primary = ((int)i == primary);
|
||||
|
||||
if (is_primary)
|
||||
{
|
||||
@@ -1840,7 +1920,6 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
||||
MetaOutputKey *output_key;
|
||||
MetaOutputConfig *output_config;
|
||||
unsigned int i;
|
||||
gboolean success;
|
||||
|
||||
if (output_num == assignment->config->n_outputs)
|
||||
return TRUE;
|
||||
@@ -1857,8 +1936,6 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
||||
&crtcs, &n_crtcs,
|
||||
&outputs, &n_outputs);
|
||||
|
||||
success = FALSE;
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &crtcs[i];
|
||||
@@ -1905,10 +1982,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
||||
output))
|
||||
{
|
||||
if (real_assign_crtcs (assignment, output_num + 1))
|
||||
{
|
||||
success = TRUE;
|
||||
goto out;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
crtc_assignment_unassign (assignment, crtc, output);
|
||||
}
|
||||
@@ -1917,8 +1991,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return success;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@@ -56,6 +56,7 @@ typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
typedef struct _MetaTileInfo MetaTileInfo;
|
||||
|
||||
typedef enum {
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
@@ -89,6 +90,17 @@ typedef enum {
|
||||
META_CONNECTOR_TYPE_DSI = 16,
|
||||
} MetaConnectorType;
|
||||
|
||||
struct _MetaTileInfo {
|
||||
guint32 group_id;
|
||||
guint32 flags;
|
||||
guint32 max_h_tiles;
|
||||
guint32 max_v_tiles;
|
||||
guint32 loc_h_tile;
|
||||
guint32 loc_v_tile;
|
||||
guint32 tile_w;
|
||||
guint32 tile_h;
|
||||
};
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
@@ -133,6 +145,7 @@ struct _MetaOutput
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
gboolean is_underscanning;
|
||||
gboolean supports_underscanning;
|
||||
|
||||
gpointer driver_private;
|
||||
GDestroyNotify driver_notify;
|
||||
@@ -141,6 +154,8 @@ struct _MetaOutput
|
||||
gboolean hotplug_mode_update;
|
||||
gint suggested_x;
|
||||
gint suggested_y;
|
||||
|
||||
MetaTileInfo tile_info;
|
||||
};
|
||||
|
||||
struct _MetaCRTC
|
||||
@@ -179,6 +194,7 @@ struct _MetaMonitorMode
|
||||
GDestroyNotify driver_notify;
|
||||
};
|
||||
|
||||
#define META_MAX_OUTPUTS_PER_MONITOR 4
|
||||
/**
|
||||
* MetaMonitorInfo:
|
||||
*
|
||||
@@ -194,6 +210,10 @@ struct _MetaMonitorInfo
|
||||
int number;
|
||||
int xinerama_index;
|
||||
MetaRectangle rect;
|
||||
/* for tiled monitors these are calculated, from untiled just copied */
|
||||
float refresh_rate;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation; /* XXX: not yet used */
|
||||
gboolean in_fullscreen;
|
||||
@@ -207,6 +227,12 @@ struct _MetaMonitorInfo
|
||||
the primary one).
|
||||
*/
|
||||
glong winsys_id;
|
||||
|
||||
guint32 tile_group_id;
|
||||
|
||||
int monitor_winsys_xid;
|
||||
int n_outputs;
|
||||
MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -324,6 +350,13 @@ struct _MetaMonitorManagerClass
|
||||
unsigned short *,
|
||||
unsigned short *,
|
||||
unsigned short *);
|
||||
|
||||
void (*add_monitor) (MetaMonitorManager *,
|
||||
MetaMonitorInfo *);
|
||||
|
||||
void (*delete_monitor) (MetaMonitorManager *,
|
||||
int monitor_winsys_xid);
|
||||
|
||||
};
|
||||
|
||||
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
|
||||
|
@@ -71,6 +71,98 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* rules for constructing a tiled monitor
|
||||
* 1. find a tile_group_id
|
||||
* 2. iterate over all outputs for that tile group id
|
||||
* 3. see if output has a crtc and if it is configured for the tile size
|
||||
* 4. calculate the total tile size
|
||||
* 5. set tile finished size
|
||||
* 6. check for more tile_group_id
|
||||
*/
|
||||
static void
|
||||
construct_tile_monitor (MetaMonitorManager *manager,
|
||||
GArray *monitor_infos,
|
||||
guint32 tile_group_id)
|
||||
{
|
||||
MetaMonitorInfo info;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < monitor_infos->len; i++)
|
||||
{
|
||||
MetaMonitorInfo *pinfo = &g_array_index (monitor_infos, MetaMonitorInfo, i);
|
||||
|
||||
if (pinfo->tile_group_id == tile_group_id)
|
||||
return;
|
||||
}
|
||||
|
||||
/* didn't find it */
|
||||
info.number = monitor_infos->len;
|
||||
info.tile_group_id = tile_group_id;
|
||||
info.is_presentation = FALSE;
|
||||
info.refresh_rate = 0.0;
|
||||
info.width_mm = 0;
|
||||
info.height_mm = 0;
|
||||
info.is_primary = FALSE;
|
||||
info.rect.x = INT_MAX;
|
||||
info.rect.y = INT_MAX;
|
||||
info.rect.width = 0;
|
||||
info.rect.height = 0;
|
||||
info.winsys_id = 0;
|
||||
info.n_outputs = 0;
|
||||
info.monitor_winsys_xid = 0;
|
||||
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (!output->tile_info.group_id)
|
||||
continue;
|
||||
|
||||
if (output->tile_info.group_id != tile_group_id)
|
||||
continue;
|
||||
|
||||
if (!output->crtc)
|
||||
continue;
|
||||
|
||||
if (output->crtc->rect.width != (int)output->tile_info.tile_w ||
|
||||
output->crtc->rect.height != (int)output->tile_info.tile_h)
|
||||
continue;
|
||||
|
||||
if (output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0)
|
||||
{
|
||||
info.refresh_rate = output->crtc->current_mode->refresh_rate;
|
||||
info.width_mm = output->width_mm;
|
||||
info.height_mm = output->height_mm;
|
||||
info.winsys_id = output->winsys_id;
|
||||
}
|
||||
|
||||
/* hack */
|
||||
if (output->crtc->rect.x < info.rect.x)
|
||||
info.rect.x = output->crtc->rect.x;
|
||||
if (output->crtc->rect.y < info.rect.y)
|
||||
info.rect.y = output->crtc->rect.y;
|
||||
|
||||
if (output->tile_info.loc_h_tile == 0)
|
||||
info.rect.height += output->tile_info.tile_h;
|
||||
|
||||
if (output->tile_info.loc_v_tile == 0)
|
||||
info.rect.width += output->tile_info.tile_w;
|
||||
|
||||
if (info.n_outputs > META_MAX_OUTPUTS_PER_MONITOR)
|
||||
continue;
|
||||
|
||||
info.outputs[info.n_outputs++] = output;
|
||||
}
|
||||
|
||||
/* if we don't have a winsys id, i.e. we haven't found tile 0,0
|
||||
don't try and add this to the monitor infos */
|
||||
if (!info.winsys_id)
|
||||
return;
|
||||
|
||||
g_array_append_val (monitor_infos, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_logical_config:
|
||||
*
|
||||
@@ -81,6 +173,7 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
|
||||
static void
|
||||
make_logical_config (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
GArray *monitor_infos;
|
||||
unsigned int i, j;
|
||||
|
||||
@@ -91,6 +184,15 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
for each of them, unless they reference a rectangle that
|
||||
is already there.
|
||||
*/
|
||||
/* for tiling we need to work out how many tiled outputs there are */
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (output->tile_info.group_id)
|
||||
construct_tile_monitor (manager, monitor_infos, output->tile_info.group_id);
|
||||
}
|
||||
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[i];
|
||||
@@ -102,8 +204,8 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
for (j = 0; j < monitor_infos->len; j++)
|
||||
{
|
||||
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
|
||||
if (meta_rectangle_equal (&crtc->rect,
|
||||
&info->rect))
|
||||
if (meta_rectangle_contains_rect (&info->rect,
|
||||
&crtc->rect))
|
||||
{
|
||||
crtc->logical_monitor = info;
|
||||
break;
|
||||
@@ -115,7 +217,9 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
MetaMonitorInfo info;
|
||||
|
||||
info.number = monitor_infos->len;
|
||||
info.tile_group_id = 0;
|
||||
info.rect = crtc->rect;
|
||||
info.refresh_rate = crtc->current_mode->refresh_rate;
|
||||
info.is_primary = FALSE;
|
||||
/* This starts true because we want
|
||||
is_presentation only if all outputs are
|
||||
@@ -125,7 +229,8 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
info.is_presentation = TRUE;
|
||||
info.in_fullscreen = -1;
|
||||
info.winsys_id = 0;
|
||||
|
||||
info.n_outputs = 0;
|
||||
info.monitor_winsys_xid = 0;
|
||||
g_array_append_val (monitor_infos, info);
|
||||
|
||||
crtc->logical_monitor = &g_array_index (monitor_infos, MetaMonitorInfo,
|
||||
@@ -147,6 +252,9 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
if (output->crtc == NULL)
|
||||
continue;
|
||||
|
||||
if (output->tile_info.group_id)
|
||||
continue;
|
||||
|
||||
/* We must have a logical monitor on every CRTC at this point */
|
||||
g_assert (output->crtc->logical_monitor != NULL);
|
||||
|
||||
@@ -155,6 +263,12 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
info->is_primary = info->is_primary || output->is_primary;
|
||||
info->is_presentation = info->is_presentation && output->is_presentation;
|
||||
|
||||
info->width_mm = output->width_mm;
|
||||
info->height_mm = output->height_mm;
|
||||
|
||||
info->outputs[0] = output;
|
||||
info->n_outputs = 1;
|
||||
|
||||
if (output->is_primary || info->winsys_id == 0)
|
||||
info->winsys_id = output->winsys_id;
|
||||
|
||||
@@ -164,6 +278,10 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
|
||||
manager->n_monitor_infos = monitor_infos->len;
|
||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||
|
||||
if (manager_class->add_monitor)
|
||||
for (i = 0; i < manager->n_monitor_infos; i++)
|
||||
manager_class->add_monitor (manager, &manager->monitor_infos[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -368,16 +486,14 @@ static char *
|
||||
make_display_name (MetaMonitorManager *manager,
|
||||
MetaOutput *output)
|
||||
{
|
||||
char *inches = NULL;
|
||||
char *vendor_name = NULL;
|
||||
char *ret;
|
||||
g_autofree char *inches = NULL;
|
||||
g_autofree char *vendor_name = NULL;
|
||||
|
||||
switch (output->connector_type)
|
||||
{
|
||||
case META_CONNECTOR_TYPE_LVDS:
|
||||
case META_CONNECTOR_TYPE_eDP:
|
||||
ret = g_strdup (_("Built-in display"));
|
||||
goto out;
|
||||
return g_strdup (_("Built-in display"));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -413,18 +529,12 @@ make_display_name (MetaMonitorManager *manager,
|
||||
/* TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
* size in inches, like 'Dell 15"'
|
||||
*/
|
||||
ret = g_strdup_printf (_("%s %s"), vendor_name, inches);
|
||||
return g_strdup_printf (_("%s %s"), vendor_name, inches);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = g_strdup (vendor_name);
|
||||
return g_strdup (vendor_name);
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (inches);
|
||||
g_free (vendor_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *
|
||||
@@ -537,6 +647,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
g_variant_new_string (get_connector_type_name (output->connector_type)));
|
||||
g_variant_builder_add (&properties, "{sv}", "underscanning",
|
||||
g_variant_new_boolean (output->is_underscanning));
|
||||
g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
|
||||
g_variant_new_boolean (output->supports_underscanning));
|
||||
|
||||
edid_file = manager_class->get_edid_file (manager, output);
|
||||
if (edid_file)
|
||||
@@ -557,6 +669,20 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
}
|
||||
}
|
||||
|
||||
if (output->tile_info.group_id)
|
||||
{
|
||||
g_variant_builder_add (&properties, "{sv}", "tile",
|
||||
g_variant_new ("(uuuuuuuu)",
|
||||
output->tile_info.group_id,
|
||||
output->tile_info.flags,
|
||||
output->tile_info.max_h_tiles,
|
||||
output->tile_info.max_v_tiles,
|
||||
output->tile_info.loc_h_tile,
|
||||
output->tile_info.loc_v_tile,
|
||||
output->tile_info.tile_w,
|
||||
output->tile_info.tile_h));
|
||||
}
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->winsys_id,
|
||||
@@ -1237,15 +1363,35 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
|
||||
void
|
||||
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
MetaMonitorInfo *old_monitor_infos;
|
||||
|
||||
unsigned old_n_monitor_infos;
|
||||
unsigned i, j;
|
||||
old_monitor_infos = manager->monitor_infos;
|
||||
old_n_monitor_infos = manager->n_monitor_infos;
|
||||
|
||||
if (manager->in_init)
|
||||
return;
|
||||
|
||||
make_logical_config (manager);
|
||||
|
||||
if (manager_class->delete_monitor)
|
||||
{
|
||||
for (i = 0; i < old_n_monitor_infos; i++)
|
||||
{
|
||||
gboolean delete_mon = TRUE;
|
||||
for (j = 0; j < manager->n_monitor_infos; j++)
|
||||
{
|
||||
if (manager->monitor_infos[j].monitor_winsys_xid == old_monitor_infos[i].monitor_winsys_xid)
|
||||
{
|
||||
delete_mon = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (delete_mon)
|
||||
manager_class->delete_monitor (manager, old_monitor_infos[i].monitor_winsys_xid);
|
||||
}
|
||||
}
|
||||
g_signal_emit_by_name (manager, "monitors-changed");
|
||||
|
||||
g_free (old_monitor_infos);
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <meta/main.h>
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include <libupower-glib/upower.h>
|
||||
|
||||
#include "meta-barrier-native.h"
|
||||
#include "meta-idle-monitor-native.h"
|
||||
@@ -39,10 +40,11 @@
|
||||
struct _MetaBackendNativePrivate
|
||||
{
|
||||
MetaLauncher *launcher;
|
||||
|
||||
MetaBarrierManagerNative *barrier_manager;
|
||||
|
||||
GSettings *keyboard_settings;
|
||||
UpClient *up_client;
|
||||
guint sleep_signal_id;
|
||||
GCancellable *cancellable;
|
||||
GDBusConnection *system_bus;
|
||||
};
|
||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
||||
|
||||
@@ -56,9 +58,69 @@ meta_backend_native_finalize (GObject *object)
|
||||
|
||||
meta_launcher_free (priv->launcher);
|
||||
|
||||
g_object_unref (priv->up_client);
|
||||
if (priv->sleep_signal_id)
|
||||
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_clear_object (&priv->cancellable);
|
||||
g_clear_object (&priv->system_bus);
|
||||
|
||||
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_for_sleep_cb (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean suspending;
|
||||
g_variant_get (parameters, "(b)", &suspending);
|
||||
if (suspending)
|
||||
return;
|
||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
||||
}
|
||||
|
||||
static void
|
||||
system_bus_gotten_cb (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackendNativePrivate *priv;
|
||||
GDBusConnection *bus;
|
||||
|
||||
bus = g_bus_get_finish (res, NULL);
|
||||
if (!bus)
|
||||
return;
|
||||
|
||||
priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
|
||||
priv->system_bus = bus;
|
||||
priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"PrepareForSleep",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
prepare_for_sleep_cb,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_is_closed_changed_cb (UpClient *client,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (up_client_get_lid_is_closed (client))
|
||||
return;
|
||||
|
||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_to_barriers (ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
@@ -270,6 +332,16 @@ meta_backend_native_init (MetaBackendNative *native)
|
||||
priv->launcher = meta_launcher_new ();
|
||||
|
||||
priv->barrier_manager = meta_barrier_manager_native_new ();
|
||||
|
||||
priv->up_client = up_client_new ();
|
||||
g_signal_connect (priv->up_client, "notify::lid-is-closed",
|
||||
G_CALLBACK (lid_is_closed_changed_cb), NULL);
|
||||
|
||||
priv->cancellable = g_cancellable_new ();
|
||||
g_bus_get (G_BUS_TYPE_SYSTEM,
|
||||
priv->cancellable,
|
||||
system_bus_gotten_cb,
|
||||
native);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
#include "meta-idle-monitor-native.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
{
|
||||
@@ -110,6 +111,7 @@ session_unpause (void)
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +130,8 @@ take_device (Login1Session *session_proxy,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GVariant *fd_variant = NULL;
|
||||
GUnixFDList *fd_list = NULL;
|
||||
g_autoptr (GVariant) fd_variant = NULL;
|
||||
g_autoptr (GUnixFDList) fd_list = NULL;
|
||||
int fd = -1;
|
||||
|
||||
if (!login1_session_call_take_device_sync (session_proxy,
|
||||
@@ -142,21 +143,14 @@ take_device (Login1Session *session_proxy,
|
||||
&fd_list,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
|
||||
if (fd == -1)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
*out_fd = fd;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (fd_variant)
|
||||
g_variant_unref (fd_variant);
|
||||
if (fd_list)
|
||||
g_object_unref (fd_list);
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -164,22 +158,16 @@ get_device_info_from_path (const char *path,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = stat (path, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
if (r < 0 || !S_ISCHR (st.st_mode))
|
||||
return FALSE;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -187,22 +175,16 @@ get_device_info_from_fd (int fd,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = fstat (fd, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
if (r < 0 || !S_ISCHR (st.st_mode))
|
||||
return FALSE;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -55,6 +55,11 @@ typedef struct {
|
||||
|
||||
uint32_t dpms_prop_id;
|
||||
uint32_t edid_blob_id;
|
||||
uint32_t tile_blob_id;
|
||||
|
||||
int suggested_x;
|
||||
int suggested_y;
|
||||
uint32_t hotplug_mode_update;
|
||||
} MetaOutputKms;
|
||||
|
||||
typedef struct {
|
||||
@@ -110,7 +115,7 @@ make_output_name (drmModeConnector *connector)
|
||||
static const char * const connector_type_names[] = {
|
||||
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
|
||||
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
|
||||
"HDMIA", "HDMIB", "TV", "eDP"
|
||||
"HDMIA", "HDMIB", "TV", "eDP", "Virtual", "DSI"
|
||||
};
|
||||
const char *connector_type_name;
|
||||
|
||||
@@ -198,6 +203,9 @@ find_connector_properties (MetaMonitorManagerKms *manager_kms,
|
||||
{
|
||||
int i;
|
||||
|
||||
output_kms->hotplug_mode_update = 0;
|
||||
output_kms->suggested_x = -1;
|
||||
output_kms->suggested_y = -1;
|
||||
for (i = 0; i < output_kms->connector->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
|
||||
@@ -208,7 +216,19 @@ find_connector_properties (MetaMonitorManagerKms *manager_kms,
|
||||
output_kms->dpms_prop_id = prop->prop_id;
|
||||
else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
|
||||
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
|
||||
|
||||
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
|
||||
strcmp (prop->name, "TILE") == 0)
|
||||
output_kms->tile_blob_id = output_kms->connector->prop_values[i];
|
||||
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
|
||||
strcmp (prop->name, "suggested X") == 0)
|
||||
output_kms->suggested_x = output_kms->connector->prop_values[i];
|
||||
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
|
||||
strcmp (prop->name, "suggested Y") == 0)
|
||||
output_kms->suggested_y = output_kms->connector->prop_values[i];
|
||||
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
|
||||
strcmp (prop->name, "hotplug_mode_update") == 0)
|
||||
output_kms->hotplug_mode_update = output_kms->connector->prop_values[i];
|
||||
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
}
|
||||
@@ -273,6 +293,47 @@ read_output_edid (MetaMonitorManagerKms *manager_kms,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_tile_info (MetaMonitorManagerKms *manager_kms,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaOutputKms *output_kms = output->driver_private;
|
||||
drmModePropertyBlobPtr tile_blob = NULL;
|
||||
int ret;
|
||||
|
||||
if (output_kms->tile_blob_id == 0)
|
||||
return FALSE;
|
||||
|
||||
tile_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->tile_blob_id);
|
||||
if (!tile_blob)
|
||||
{
|
||||
meta_warning ("Failed to read TILE of output %s: %s\n", output->name, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (tile_blob->length > 0)
|
||||
{
|
||||
ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d",
|
||||
&output->tile_info.group_id,
|
||||
&output->tile_info.flags,
|
||||
&output->tile_info.max_h_tiles,
|
||||
&output->tile_info.max_v_tiles,
|
||||
&output->tile_info.loc_h_tile,
|
||||
&output->tile_info.loc_v_tile,
|
||||
&output->tile_info.tile_w,
|
||||
&output->tile_info.tile_h);
|
||||
|
||||
if (ret != 8)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
drmModeFreePropertyBlob (tile_blob);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaMonitorMode *
|
||||
find_meta_mode (MetaMonitorManager *manager,
|
||||
const drmModeModeInfo *drm_mode)
|
||||
@@ -516,8 +577,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
meta_output->suggested_x = -1;
|
||||
meta_output->suggested_y = -1;
|
||||
|
||||
switch (connector->subpixel)
|
||||
{
|
||||
@@ -542,11 +601,17 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
break;
|
||||
}
|
||||
|
||||
meta_output->preferred_mode = NULL;
|
||||
meta_output->n_modes = connector->count_modes;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
for (j = 0; j < meta_output->n_modes; j++)
|
||||
for (j = 0; j < meta_output->n_modes; j++) {
|
||||
meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
|
||||
meta_output->preferred_mode = meta_output->modes[0];
|
||||
if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED)
|
||||
meta_output->preferred_mode = meta_output->modes[j];
|
||||
}
|
||||
|
||||
if (!meta_output->preferred_mode)
|
||||
meta_output->preferred_mode = meta_output->modes[0];
|
||||
|
||||
output_kms->connector = connector;
|
||||
output_kms->n_encoders = connector->count_encoders;
|
||||
@@ -612,7 +677,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
}
|
||||
|
||||
find_connector_properties (manager_kms, output_kms);
|
||||
|
||||
meta_output->suggested_x = output_kms->suggested_x;
|
||||
meta_output->suggested_y = output_kms->suggested_y;
|
||||
meta_output->hotplug_mode_update = output_kms->hotplug_mode_update;
|
||||
|
||||
edid = read_output_edid (manager_kms, meta_output);
|
||||
meta_output_parse_edid (meta_output, edid);
|
||||
g_bytes_unref (edid);
|
||||
@@ -622,6 +690,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
|
||||
meta_output->scale = get_output_scale (manager, meta_output);
|
||||
|
||||
output_get_tile_info (manager_kms, meta_output);
|
||||
|
||||
/* FIXME: backlight is a very driver specific thing unfortunately,
|
||||
every DDX does its own thing, and the dumb KMS API does not include it.
|
||||
|
||||
|
@@ -46,6 +46,14 @@
|
||||
#include "display-private.h"
|
||||
#include "compositor/compositor-private.h"
|
||||
|
||||
typedef enum {
|
||||
/* We're a traditional CM running under the host. */
|
||||
META_BACKEND_X11_MODE_COMPOSITOR,
|
||||
|
||||
/* We're a nested X11 client */
|
||||
META_BACKEND_X11_MODE_NESTED,
|
||||
} MetaBackendX11Mode;
|
||||
|
||||
struct _MetaBackendX11Private
|
||||
{
|
||||
/* The host X11 display */
|
||||
@@ -53,6 +61,8 @@ struct _MetaBackendX11Private
|
||||
xcb_connection_t *xcb;
|
||||
GSource *source;
|
||||
|
||||
MetaBackendX11Mode mode;
|
||||
|
||||
int xsync_event_base;
|
||||
int xsync_error_base;
|
||||
|
||||
@@ -102,7 +112,7 @@ translate_device_event (MetaBackendX11 *x11,
|
||||
/* This codepath should only ever trigger as an X11 compositor,
|
||||
* and never under nested, as under nested all backend events
|
||||
* should be reported with respect to the stage window. */
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
|
||||
|
||||
device_event->event = stage_window;
|
||||
|
||||
@@ -133,6 +143,8 @@ static void
|
||||
translate_crossing_event (MetaBackendX11 *x11,
|
||||
XIEnterEvent *enter_event)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
/* Throw out weird events generated by grabs. */
|
||||
if (enter_event->mode == XINotifyGrab ||
|
||||
enter_event->mode == XINotifyUngrab)
|
||||
@@ -141,7 +153,15 @@ translate_crossing_event (MetaBackendX11 *x11,
|
||||
return;
|
||||
}
|
||||
|
||||
enter_event->event = meta_backend_x11_get_xwindow (x11);
|
||||
Window stage_window = meta_backend_x11_get_xwindow (x11);
|
||||
if (enter_event->event != stage_window)
|
||||
{
|
||||
/* See above for the rationale for this... */
|
||||
g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
|
||||
enter_event->event = meta_backend_x11_get_xwindow (x11);
|
||||
enter_event->event_x = enter_event->root_x;
|
||||
enter_event->event_y = enter_event->root_y;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -430,7 +450,9 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
take_touch_grab (backend);
|
||||
/* We only take the passive touch grab if we are a X11 compositor */
|
||||
if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
|
||||
take_touch_grab (backend);
|
||||
|
||||
priv->xcb = XGetXCBConnection (priv->xdisplay);
|
||||
if (!xkb_x11_setup_xkb_extension (priv->xcb,
|
||||
@@ -461,13 +483,18 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend,
|
||||
static MetaMonitorManager *
|
||||
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
/* If we're a Wayland compositor using the X11 backend,
|
||||
* we're a nested configuration, so return the dummy
|
||||
* monitor setup. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
|
||||
switch (priv->mode)
|
||||
{
|
||||
case META_BACKEND_X11_MODE_COMPOSITOR:
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
|
||||
case META_BACKEND_X11_MODE_NESTED:
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
@@ -721,7 +748,10 @@ static void
|
||||
meta_backend_x11_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
|
||||
{
|
||||
/* For a nested wayland session, we want to go through Clutter to update the
|
||||
* toplevel window size, rather than doing it directly.
|
||||
@@ -755,9 +785,21 @@ meta_backend_x11_select_stage_events (MetaBackend *backend)
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
|
||||
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
|
||||
{
|
||||
/* When we're an X11 compositor, we can't take these events or else
|
||||
* replaying events from our passive root window grab will cause
|
||||
* them to come back to us.
|
||||
*
|
||||
* When we're a nested application, we want to behave like any other
|
||||
* application, so select these events like normal apps do.
|
||||
*/
|
||||
XISetMask (mask.mask, XI_TouchBegin);
|
||||
XISetMask (mask.mask, XI_TouchEnd);
|
||||
XISetMask (mask.mask, XI_TouchUpdate);
|
||||
}
|
||||
|
||||
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
|
||||
}
|
||||
|
||||
@@ -783,8 +825,15 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
static void
|
||||
meta_backend_x11_init (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
/* We do X11 event retrieval ourselves */
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
priv->mode = META_BACKEND_X11_MODE_NESTED;
|
||||
else
|
||||
priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
|
||||
}
|
||||
|
||||
Display *
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "meta-backend-x11.h"
|
||||
#include "meta-input-settings-x11.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
@@ -35,6 +36,41 @@
|
||||
|
||||
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
|
||||
|
||||
static void *
|
||||
get_property (ClutterInputDevice *device,
|
||||
const gchar *property,
|
||||
Atom type,
|
||||
int format,
|
||||
gulong nitems)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
gulong nitems_ret, bytes_after_ret;
|
||||
int rc, device_id, format_ret;
|
||||
Atom property_atom, type_ret;
|
||||
guchar *data_ret = NULL;
|
||||
|
||||
property_atom = XInternAtom (xdisplay, property, True);
|
||||
if (!property_atom)
|
||||
return NULL;
|
||||
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
rc = XIGetProperty (xdisplay, device_id, property_atom,
|
||||
0, 10, False, type, &type_ret, &format_ret,
|
||||
&nitems_ret, &bytes_after_ret, &data_ret);
|
||||
if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
|
||||
{
|
||||
if (nitems_ret > nitems)
|
||||
g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
|
||||
property, clutter_input_device_get_device_name (device), nitems_ret, nitems);
|
||||
return data_ret;
|
||||
}
|
||||
|
||||
meta_XFree (data_ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
change_property (ClutterInputDevice *device,
|
||||
const gchar *property,
|
||||
@@ -45,23 +81,23 @@ change_property (ClutterInputDevice *device,
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
gulong nitems_ret, bytes_after_ret;
|
||||
int rc, device_id, format_ret;
|
||||
Atom property_atom, type_ret;
|
||||
int device_id;
|
||||
Atom property_atom;
|
||||
guchar *data_ret;
|
||||
|
||||
property_atom = XInternAtom (xdisplay, property, False);
|
||||
property_atom = XInternAtom (xdisplay, property, True);
|
||||
if (!property_atom)
|
||||
return;
|
||||
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
rc = XIGetProperty (xdisplay, device_id, property_atom,
|
||||
0, 0, False, type, &type_ret, &format_ret,
|
||||
&nitems_ret, &bytes_after_ret, &data_ret);
|
||||
data_ret = get_property (device, property, type, format, nitems);
|
||||
if (!data_ret)
|
||||
return;
|
||||
|
||||
XIChangeProperty (xdisplay, device_id, property_atom, type,
|
||||
format, XIPropModeReplace, data, nitems);
|
||||
meta_XFree (data_ret);
|
||||
|
||||
if (rc == Success && type_ret == type && format_ret == format)
|
||||
XIChangeProperty (xdisplay, device_id, property_atom, type,
|
||||
format, XIPropModeReplace, data, nitems);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -190,16 +226,23 @@ meta_input_settings_x11_set_click_method (MetaInputSettings *settings,
|
||||
GDesktopTouchpadClickMethod mode)
|
||||
{
|
||||
guchar values[2] = { 0 }; /* buttonareas, clickfinger */
|
||||
guchar *defaults;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
|
||||
defaults = get_property (device, "libinput Click Method Enabled Default",
|
||||
XA_INTEGER, 8, 2);
|
||||
if (!defaults)
|
||||
break;
|
||||
memcpy (values, defaults, 2);
|
||||
meta_XFree (defaults);
|
||||
break;
|
||||
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
|
||||
break;
|
||||
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
|
||||
values[0] = 1;
|
||||
break;
|
||||
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
|
||||
/* XXX: We can't be much smarter yet, x11 doesn't expose default settings */
|
||||
case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
|
||||
values[1] = 1;
|
||||
break;
|
||||
|
@@ -58,6 +58,7 @@ struct _MetaMonitorManagerXrandr
|
||||
XRRScreenResources *resources;
|
||||
int rr_event_base;
|
||||
int rr_error_base;
|
||||
gboolean has_randr15;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerXrandrClass
|
||||
@@ -194,11 +195,10 @@ static gboolean
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean value = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
@@ -209,13 +209,9 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return value;
|
||||
return ((int*)buffer)[0];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -229,12 +225,11 @@ static gboolean
|
||||
output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
gboolean value = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
char *str;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
g_autofree char *str = NULL;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
@@ -244,17 +239,56 @@ output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_ATOM || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
goto out;
|
||||
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
||||
return FALSE;
|
||||
|
||||
str = XGetAtomName (manager_xrandr->xdisplay, *(Atom *)buffer);
|
||||
value = !strcmp(str, "on");
|
||||
XFree (str);
|
||||
return (strcmp (str, "on") == 0);
|
||||
}
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return value;
|
||||
static gboolean
|
||||
output_get_supports_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom, actual_type;
|
||||
int actual_format, i;
|
||||
unsigned long nitems, bytes_after;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
XRRPropertyInfo *property_info;
|
||||
Atom *values;
|
||||
gboolean supports_underscanning = FALSE;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_ATOM,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
||||
return FALSE;
|
||||
|
||||
property_info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID) output->winsys_id,
|
||||
atom);
|
||||
values = (Atom *) property_info->values;
|
||||
|
||||
for (i = 0; i < property_info->num_values; i++)
|
||||
{
|
||||
/* The output supports underscanning if "on" is a valid value
|
||||
* for the underscan property.
|
||||
*/
|
||||
char *name = XGetAtomName (manager_xrandr->xdisplay, values[i]);
|
||||
if (strcmp (name, "on") == 0)
|
||||
supports_underscanning = TRUE;
|
||||
|
||||
XFree (name);
|
||||
}
|
||||
|
||||
XFree (property_info);
|
||||
|
||||
return supports_underscanning;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -273,7 +307,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
@@ -284,12 +318,9 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
if (value > 0)
|
||||
return normalize_backlight (output, value);
|
||||
else
|
||||
@@ -302,7 +333,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
{
|
||||
Atom atom;
|
||||
xcb_connection_t *xcb_conn;
|
||||
xcb_randr_query_output_property_reply_t *reply;
|
||||
g_autofree xcb_randr_query_output_property_reply_t *reply;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
|
||||
@@ -320,15 +351,12 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
if (!reply->range || reply->length != 2)
|
||||
{
|
||||
meta_verbose ("backlight %s was not range\n", output->name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
|
||||
output->backlight_min = values[0];
|
||||
output->backlight_max = values[1];
|
||||
|
||||
out:
|
||||
free (reply);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -408,6 +436,42 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
output_get_tile_info (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom tile_atom;
|
||||
unsigned char *prop;
|
||||
unsigned long nitems, bytes_after;
|
||||
int actual_format;
|
||||
Atom actual_type;
|
||||
|
||||
if (manager_xrandr->has_randr15 == FALSE)
|
||||
return;
|
||||
|
||||
tile_atom = XInternAtom (manager_xrandr->xdisplay, "TILE", FALSE);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
output->winsys_id,
|
||||
tile_atom, 0, 100, False,
|
||||
False, AnyPropertyType,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &prop);
|
||||
|
||||
if (actual_type == XA_INTEGER && actual_format == 32 && nitems == 8)
|
||||
{
|
||||
long *values = (long *)prop;
|
||||
output->tile_info.group_id = values[0];
|
||||
output->tile_info.flags = values[1];
|
||||
output->tile_info.max_h_tiles = values[2];
|
||||
output->tile_info.max_v_tiles = values[3];
|
||||
output->tile_info.loc_h_tile = values[4];
|
||||
output->tile_info.loc_v_tile = values[5];
|
||||
output->tile_info.tile_w = values[6];
|
||||
output->tile_info.tile_h = values[7];
|
||||
}
|
||||
XFree (prop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
@@ -479,11 +543,10 @@ static MetaConnectorType
|
||||
output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaConnectorType ret = META_CONNECTOR_TYPE_Unknown;
|
||||
Atom atom, actual_type, connector_type_atom;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
@@ -494,14 +557,10 @@ output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
return META_CONNECTOR_TYPE_Unknown;
|
||||
|
||||
connector_type_atom = ((Atom *) buffer)[0];
|
||||
ret = connector_type_from_atom (manager_xrandr, connector_type_atom);
|
||||
|
||||
out:
|
||||
meta_XFree (buffer);
|
||||
return ret;
|
||||
return connector_type_from_atom (manager_xrandr, connector_type_atom);
|
||||
}
|
||||
|
||||
static MetaConnectorType
|
||||
@@ -538,7 +597,7 @@ output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
if (g_str_has_prefix (name, "Virtual"))
|
||||
return META_CONNECTOR_TYPE_VIRTUAL;
|
||||
if (g_str_has_prefix (name, "Composite"))
|
||||
return META_CONNECTOR_TYPE_VGA;
|
||||
return META_CONNECTOR_TYPE_Composite;
|
||||
if (g_str_has_prefix (name, "S-video"))
|
||||
return META_CONNECTOR_TYPE_SVIDEO;
|
||||
if (g_str_has_prefix (name, "TV"))
|
||||
@@ -736,6 +795,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
|
||||
meta_output->connector_type = output_get_connector_type (manager_xrandr, meta_output);
|
||||
|
||||
output_get_tile_info (manager_xrandr, meta_output);
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
for (j = 0; j < meta_output->n_modes; j++)
|
||||
@@ -789,6 +849,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
|
||||
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
|
||||
meta_output->is_underscanning = output_get_underscanning_xrandr (manager_xrandr, meta_output);
|
||||
meta_output->supports_underscanning = output_get_supports_underscanning_xrandr (manager_xrandr, meta_output);
|
||||
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
|
||||
|
||||
if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
|
||||
@@ -902,11 +963,12 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
int value = presentation;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
|
||||
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
|
||||
(XID)output->winsys_id,
|
||||
atom, XCB_ATOM_CARDINAL, 32,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
1, &value);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -921,11 +983,12 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
value = underscanning ? "on" : "off";
|
||||
valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
prop,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char*) &valueatom, 1);
|
||||
|
||||
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
|
||||
(XID)output->winsys_id,
|
||||
prop, XCB_ATOM_ATOM, 32,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
1, &valueatom);
|
||||
|
||||
/* Configure the border at the same time. Currently, we use a
|
||||
* 5% of the width/height of the mode. In the future, we should
|
||||
@@ -936,19 +999,21 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
|
||||
border_value = output->crtc->current_mode->width * 0.05;
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
prop,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &border_value, 1);
|
||||
|
||||
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
|
||||
(XID)output->winsys_id,
|
||||
prop, XCB_ATOM_INTEGER, 32,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
1, &border_value);
|
||||
|
||||
prop = XInternAtom (manager_xrandr->xdisplay, "underscan vborder", False);
|
||||
border_value = output->crtc->current_mode->height * 0.05;
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
prop,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &border_value, 1);
|
||||
|
||||
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
|
||||
(XID)output->winsys_id,
|
||||
prop, XCB_ATOM_INTEGER, 32,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
1, &border_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,7 +1133,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
if (crtc_info->mode != NULL)
|
||||
{
|
||||
MetaMonitorMode *mode;
|
||||
XID *outputs;
|
||||
g_autofree XID *outputs = NULL;
|
||||
unsigned int j, n_outputs;
|
||||
int width, height;
|
||||
Status ok;
|
||||
@@ -1105,7 +1170,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
|
||||
mode->width, mode->height, (float)mode->refresh_rate,
|
||||
crtc_info->x, crtc_info->y, crtc_info->transform);
|
||||
goto next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||
@@ -1125,9 +1190,6 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
crtc->rect.height = height;
|
||||
crtc->current_mode = mode;
|
||||
crtc->transform = crtc_info->transform;
|
||||
|
||||
next:
|
||||
g_free (outputs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,9 +1209,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output_info->output,
|
||||
output_info->is_presentation);
|
||||
|
||||
output_set_underscanning_xrandr (manager_xrandr,
|
||||
output_info->output,
|
||||
output_info->is_underscanning);
|
||||
if (output_get_supports_underscanning_xrandr (manager_xrandr, output_info->output))
|
||||
output_set_underscanning_xrandr (manager_xrandr,
|
||||
output_info->output,
|
||||
output_info->is_underscanning);
|
||||
|
||||
output->is_primary = output_info->is_primary;
|
||||
output->is_presentation = output_info->is_presentation;
|
||||
@@ -1187,11 +1250,12 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
|
||||
xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
|
||||
(XID)output->winsys_id,
|
||||
atom, XCB_ATOM_INTEGER, 32,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
1, &hw_value);
|
||||
|
||||
/* We're not selecting for property notifies, so update the value immediately */
|
||||
output->backlight = normalize_backlight (output, hw_value);
|
||||
@@ -1239,6 +1303,88 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
XRRFreeGamma (gamma);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XRANDR15
|
||||
static void
|
||||
meta_monitor_manager_xrandr_add_monitor(MetaMonitorManager *manager,
|
||||
MetaMonitorInfo *monitor)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
XRRMonitorInfo *m;
|
||||
int o;
|
||||
Atom name;
|
||||
char name_buf[40];
|
||||
|
||||
if (manager_xrandr->has_randr15 == FALSE)
|
||||
return;
|
||||
|
||||
if (monitor->n_outputs <= 1)
|
||||
return;
|
||||
|
||||
if (monitor->outputs[0]->product)
|
||||
snprintf (name_buf, 40, "%s-%d", monitor->outputs[0]->product, monitor->outputs[0]->tile_info.group_id);
|
||||
else
|
||||
snprintf (name_buf, 40, "Tiled-%d", monitor->outputs[0]->tile_info.group_id);
|
||||
|
||||
name = XInternAtom (manager_xrandr->xdisplay, name_buf, False);
|
||||
monitor->monitor_winsys_xid = name;
|
||||
m = XRRAllocateMonitor (manager_xrandr->xdisplay, monitor->n_outputs);
|
||||
if (!m)
|
||||
return;
|
||||
m->name = name;
|
||||
m->primary = monitor->is_primary;
|
||||
m->automatic = True;
|
||||
|
||||
for (o = 0; o < monitor->n_outputs; o++) {
|
||||
MetaOutput *output = monitor->outputs[o];
|
||||
m->outputs[o] = output->winsys_id;
|
||||
}
|
||||
XRRSetMonitor (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
m);
|
||||
XRRFreeMonitors (m);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_delete_monitor(MetaMonitorManager *manager,
|
||||
int monitor_winsys_xid)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
if (manager_xrandr->has_randr15 == FALSE)
|
||||
return;
|
||||
XRRDeleteMonitor (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
monitor_winsys_xid);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init_monitors(MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
XRRMonitorInfo *m;
|
||||
int n, i;
|
||||
|
||||
if (manager_xrandr->has_randr15 == FALSE)
|
||||
return;
|
||||
|
||||
/* delete any tiled monitors setup, as mutter will want to recreate
|
||||
things in its image */
|
||||
m = XRRGetMonitors (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
FALSE, &n);
|
||||
if (n == -1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (m[i].noutput > 1)
|
||||
XRRDeleteMonitor (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
m[i].name);
|
||||
}
|
||||
XRRFreeMonitors (m);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
@@ -1254,6 +1400,7 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
}
|
||||
else
|
||||
{
|
||||
int major_version, minor_version;
|
||||
/* We only use ScreenChangeNotify, but GDK uses the others,
|
||||
and we don't want to step on its toes */
|
||||
XRRSelectInput (manager_xrandr->xdisplay,
|
||||
@@ -1261,6 +1408,17 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
RRScreenChangeNotifyMask
|
||||
| RRCrtcChangeNotifyMask
|
||||
| RROutputPropertyNotifyMask);
|
||||
|
||||
manager_xrandr->has_randr15 = FALSE;
|
||||
XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
|
||||
&minor_version);
|
||||
#ifdef HAVE_XRANDR15
|
||||
if (major_version > 1 ||
|
||||
(major_version == 1 &&
|
||||
minor_version >= 5))
|
||||
manager_xrandr->has_randr15 = TRUE;
|
||||
meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,6 +1449,10 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
||||
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
||||
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
||||
#ifdef HAVE_XRANDR15
|
||||
manager_class->add_monitor = meta_monitor_manager_xrandr_add_monitor;
|
||||
manager_class->delete_monitor = meta_monitor_manager_xrandr_delete_monitor;
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -32,6 +32,9 @@
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *texture);
|
||||
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
|
||||
guint fallback_width,
|
||||
guint fallback_height);
|
||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
|
||||
|
||||
#endif
|
||||
|
@@ -86,6 +86,7 @@ struct _MetaShapedTexturePrivate
|
||||
cairo_region_t *unobscured_region;
|
||||
|
||||
guint tex_width, tex_height;
|
||||
guint fallback_width, fallback_height;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
@@ -136,7 +137,20 @@ set_unobscured_region (MetaShapedTexture *self,
|
||||
g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
|
||||
guint width, height;
|
||||
|
||||
if (priv->texture)
|
||||
{
|
||||
width = priv->tex_width;
|
||||
height = priv->tex_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = priv->fallback_width;
|
||||
height = priv->fallback_height;
|
||||
}
|
||||
|
||||
cairo_rectangle_int_t bounds = { 0, 0, width, height };
|
||||
priv->unobscured_region = cairo_region_copy (unobscured_region);
|
||||
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
|
||||
}
|
||||
@@ -498,17 +512,18 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
guint width;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
|
||||
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
if (priv->texture)
|
||||
width = priv->tex_width;
|
||||
else
|
||||
width = priv->fallback_width;
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = priv->tex_width;
|
||||
|
||||
*min_width_p = width;
|
||||
if (natural_width_p)
|
||||
*natural_width_p = priv->tex_width;
|
||||
*natural_width_p = width;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -517,17 +532,18 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
guint height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
|
||||
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
if (priv->texture)
|
||||
height = priv->tex_height;
|
||||
else
|
||||
height = priv->fallback_height;
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = priv->tex_height;
|
||||
|
||||
*min_height_p = height;
|
||||
if (natural_height_p)
|
||||
*natural_height_p = priv->tex_height;
|
||||
*natural_height_p = height;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
@@ -860,6 +876,17 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_fallback_size (MetaShapedTexture *self,
|
||||
guint fallback_width,
|
||||
guint fallback_height)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
priv->fallback_width = fallback_width;
|
||||
priv->fallback_height = fallback_height;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
|
@@ -416,6 +416,7 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
if (priv->last_width == width &&
|
||||
priv->last_height == height)
|
||||
@@ -424,4 +425,5 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
priv->size_changed = TRUE;
|
||||
priv->last_width = width;
|
||||
priv->last_height = height;
|
||||
meta_shaped_texture_set_fallback_size (stex, width, height);
|
||||
}
|
||||
|
@@ -160,12 +160,7 @@ void
|
||||
meta_window_set_alive (MetaWindow *window,
|
||||
gboolean is_alive)
|
||||
{
|
||||
if (window->is_alive == is_alive)
|
||||
return;
|
||||
|
||||
window->is_alive = is_alive;
|
||||
|
||||
if (window->is_alive)
|
||||
if (is_alive)
|
||||
kill_delete_dialog (window);
|
||||
else
|
||||
show_delete_dialog (window, CurrentTime);
|
||||
|
@@ -217,9 +217,6 @@ struct _MetaDisplay
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_frame_action : 1;
|
||||
/* During a resize operation, the directions in which we've broken
|
||||
* out of the initial maximization state */
|
||||
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
|
@@ -1922,7 +1922,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_last_moveresize_time.tv_usec = 0;
|
||||
display->grab_last_user_action_was_snap = FALSE;
|
||||
display->grab_frame_action = frame_action;
|
||||
display->grab_resize_unmaximize = 0;
|
||||
|
||||
meta_display_update_cursor (display);
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
@@ -53,7 +54,6 @@ typedef struct _MetaResolvedKeyCombo {
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
|
@@ -176,7 +176,6 @@ static gboolean
|
||||
accelerator_parse (const gchar *accelerator,
|
||||
MetaKeyCombo *combo)
|
||||
{
|
||||
gboolean error = FALSE;
|
||||
guint keyval, keycode;
|
||||
MetaVirtualModifier mods;
|
||||
gint len;
|
||||
@@ -186,10 +185,7 @@ accelerator_parse (const gchar *accelerator,
|
||||
combo->modifiers = 0;
|
||||
|
||||
if (accelerator == NULL)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
keyval = 0;
|
||||
keycode = 0;
|
||||
@@ -310,10 +306,7 @@ accelerator_parse (const gchar *accelerator,
|
||||
g_free (with_xf86);
|
||||
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,14 +315,10 @@ accelerator_parse (const gchar *accelerator,
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (error)
|
||||
return FALSE;
|
||||
|
||||
out:
|
||||
combo->keysym = keyval;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -750,7 +750,7 @@ void
|
||||
meta_screen_init_workspaces (MetaScreen *screen)
|
||||
{
|
||||
MetaWorkspace *current_workspace;
|
||||
gulong current_workspace_index = 0;
|
||||
uint32_t current_workspace_index = 0;
|
||||
guint32 timestamp;
|
||||
|
||||
g_return_if_fail (META_IS_SCREEN (screen));
|
||||
@@ -1166,7 +1166,7 @@ update_num_workspaces (MetaScreen *screen,
|
||||
if (meta_prefs_get_dynamic_workspaces ())
|
||||
{
|
||||
int n_items;
|
||||
gulong *list;
|
||||
uint32_t *list;
|
||||
|
||||
n_items = 0;
|
||||
list = NULL;
|
||||
@@ -1755,7 +1755,7 @@ meta_screen_get_monitor_geometry (MetaScreen *screen,
|
||||
void
|
||||
meta_screen_update_workspace_layout (MetaScreen *screen)
|
||||
{
|
||||
gulong *list;
|
||||
uint32_t *list;
|
||||
int n_items;
|
||||
|
||||
if (screen->workspace_layout_overridden)
|
||||
|
@@ -1273,16 +1273,13 @@ get_default_focus_window (MetaStack *stack,
|
||||
if (window->unmaps_pending > 0)
|
||||
continue;
|
||||
|
||||
if (window->minimized)
|
||||
continue;
|
||||
|
||||
if (window->unmanaging)
|
||||
continue;
|
||||
|
||||
if (!(window->input || window->take_focus))
|
||||
continue;
|
||||
|
||||
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
|
||||
if (!meta_window_should_be_showing (window))
|
||||
continue;
|
||||
|
||||
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
||||
|
@@ -434,7 +434,6 @@ struct _MetaWindow
|
||||
|
||||
/* Managed by delete.c */
|
||||
int dialog_pid;
|
||||
guint is_alive : 1;
|
||||
|
||||
/* maintained by group.c */
|
||||
MetaGroup *group;
|
||||
|
@@ -58,6 +58,7 @@
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-window-wayland.h"
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
@@ -723,6 +724,12 @@ meta_window_should_attach_to_parent (MetaWindow *window)
|
||||
static gboolean
|
||||
client_window_should_be_mapped (MetaWindow *window)
|
||||
{
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->surface->buffer)
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return !window->shaded;
|
||||
}
|
||||
|
||||
@@ -1533,6 +1540,12 @@ meta_window_showing_on_its_workspace (MetaWindow *window)
|
||||
gboolean
|
||||
meta_window_should_be_showing (MetaWindow *window)
|
||||
{
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->surface->buffer)
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
/* Windows should be showing if they're located on the
|
||||
* active workspace and they're showing on their own workspace. */
|
||||
return (meta_window_located_on_workspace (window, window->screen->active_workspace) &&
|
||||
@@ -2965,11 +2978,9 @@ unmaximize_window_before_freeing (MetaWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_unmaximize_internal (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
MetaRectangle *desired_rect,
|
||||
int gravity)
|
||||
void
|
||||
meta_window_unmaximize (MetaWindow *window,
|
||||
MetaMaximizeFlags directions)
|
||||
{
|
||||
gboolean unmaximize_horizontally, unmaximize_vertically;
|
||||
MetaRectangle new_rect;
|
||||
@@ -2990,6 +3001,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
if ((unmaximize_horizontally && window->maximized_horizontally) ||
|
||||
(unmaximize_vertically && window->maximized_vertically))
|
||||
{
|
||||
MetaRectangle *desired_rect;
|
||||
MetaRectangle target_rect;
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle old_rect;
|
||||
@@ -3015,6 +3027,8 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
*/
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
desired_rect = &window->saved_rect;
|
||||
|
||||
/* Unmaximize to the saved_rect position in the direction(s)
|
||||
* being unmaximized.
|
||||
*/
|
||||
@@ -3061,7 +3075,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION | META_MOVE_RESIZE_STATE_CHANGED,
|
||||
gravity,
|
||||
NorthWestGravity,
|
||||
target_rect);
|
||||
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
@@ -3095,37 +3109,6 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_unmaximize (MetaWindow *window,
|
||||
MetaMaximizeFlags directions)
|
||||
{
|
||||
meta_window_unmaximize_internal (window, directions, &window->saved_rect,
|
||||
NorthWestGravity);
|
||||
}
|
||||
|
||||
/* Like meta_window_unmaximize(), but instead of unmaximizing to the
|
||||
* saved position, we give the new desired size, and the gravity that
|
||||
* determines the positioning relationship between the area occupied
|
||||
* maximized and the new are. The arguments are similar to
|
||||
* meta_window_resize_with_gravity().
|
||||
* Unlike meta_window_unmaximize(), tiling is not restored for windows
|
||||
* with a tile mode other than META_TILE_NONE.
|
||||
*/
|
||||
static void
|
||||
meta_window_unmaximize_with_gravity (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
int new_width,
|
||||
int new_height,
|
||||
int gravity)
|
||||
{
|
||||
MetaRectangle desired_rect;
|
||||
|
||||
desired_rect.width = new_width;
|
||||
desired_rect.height = new_height;
|
||||
|
||||
meta_window_unmaximize_internal (window, directions, &desired_rect, gravity);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_make_above (MetaWindow *window)
|
||||
{
|
||||
@@ -3228,6 +3211,8 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
window->fullscreen = FALSE;
|
||||
target_rect = window->saved_rect;
|
||||
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
/* Window's size hints may have changed while maximized, making
|
||||
* saved_rect invalid. #329152
|
||||
*/
|
||||
@@ -5728,81 +5713,6 @@ update_move (MetaWindow *window,
|
||||
meta_window_move_frame (window, TRUE, new_x, new_y);
|
||||
}
|
||||
|
||||
/* When resizing a maximized window by using alt-middle-drag (resizing
|
||||
* with the grips or the menu for a maximized window is not enabled),
|
||||
* the user can "break" out of the maximized state. This checks for
|
||||
* that possibility. During such a break-out resize the user can also
|
||||
* return to the previous maximization state by resizing back to near
|
||||
* the original size.
|
||||
*/
|
||||
static MetaMaximizeFlags
|
||||
check_resize_unmaximize(MetaWindow *window,
|
||||
int dx,
|
||||
int dy)
|
||||
{
|
||||
int threshold;
|
||||
MetaMaximizeFlags new_unmaximize;
|
||||
|
||||
#define DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR 3
|
||||
|
||||
threshold = meta_prefs_get_drag_threshold () *
|
||||
DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR;
|
||||
new_unmaximize = 0;
|
||||
|
||||
if (window->maximized_horizontally ||
|
||||
window->tile_mode != META_TILE_NONE ||
|
||||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0)
|
||||
{
|
||||
int x_amount;
|
||||
|
||||
/* We allow breaking out of maximization in either direction, to make
|
||||
* the window larger than the monitor as well as smaller than the
|
||||
* monitor. If we wanted to only allow resizing smaller than the
|
||||
* monitor, we'd use - dx for NE/E/SE and dx for SW/W/NW.
|
||||
*/
|
||||
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) != 0)
|
||||
x_amount = dx < 0 ? - dx : dx;
|
||||
else
|
||||
x_amount = 0;
|
||||
|
||||
if (x_amount > threshold)
|
||||
new_unmaximize |= META_MAXIMIZE_HORIZONTAL;
|
||||
}
|
||||
|
||||
if (window->maximized_vertically ||
|
||||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0)
|
||||
{
|
||||
int y_amount;
|
||||
|
||||
if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) != 0)
|
||||
y_amount = dy < 0 ? - dy : dy;
|
||||
else
|
||||
y_amount = 0;
|
||||
|
||||
if (y_amount > threshold)
|
||||
new_unmaximize |= META_MAXIMIZE_VERTICAL;
|
||||
}
|
||||
|
||||
/* Metacity doesn't have a full user interface for only horizontally or
|
||||
* vertically maximized, so while only unmaximizing in the direction drags
|
||||
* has some advantages, it will also confuse the user. So, we always
|
||||
* unmaximize both ways if possible.
|
||||
*/
|
||||
if (new_unmaximize != 0)
|
||||
{
|
||||
new_unmaximize = 0;
|
||||
|
||||
if (window->maximized_horizontally ||
|
||||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0)
|
||||
new_unmaximize |= META_MAXIMIZE_HORIZONTAL;
|
||||
if (window->maximized_vertically ||
|
||||
(window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0)
|
||||
new_unmaximize |= META_MAXIMIZE_VERTICAL;
|
||||
}
|
||||
|
||||
return new_unmaximize;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_resize_timeout (gpointer data)
|
||||
{
|
||||
@@ -5827,7 +5737,6 @@ update_resize (MetaWindow *window,
|
||||
int gravity;
|
||||
MetaRectangle old;
|
||||
double remaining = 0;
|
||||
MetaMaximizeFlags new_unmaximize;
|
||||
|
||||
window->display->grab_latest_motion_x = x;
|
||||
window->display->grab_latest_motion_y = y;
|
||||
@@ -5874,8 +5783,6 @@ update_resize (MetaWindow *window,
|
||||
meta_window_update_keyboard_resize (window, TRUE);
|
||||
}
|
||||
|
||||
new_unmaximize = check_resize_unmaximize (window, dx, dy);
|
||||
|
||||
if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST)
|
||||
new_w += dx;
|
||||
else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST)
|
||||
@@ -5944,29 +5851,7 @@ update_resize (MetaWindow *window,
|
||||
snap,
|
||||
FALSE);
|
||||
|
||||
if (new_unmaximize == window->display->grab_resize_unmaximize)
|
||||
{
|
||||
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0)
|
||||
{
|
||||
meta_window_unmaximize_with_gravity (window,
|
||||
(new_unmaximize & ~window->display->grab_resize_unmaximize),
|
||||
new_w, new_h, gravity);
|
||||
}
|
||||
|
||||
if ((window->display->grab_resize_unmaximize & ~new_unmaximize))
|
||||
{
|
||||
MetaRectangle saved_rect = window->saved_rect;
|
||||
meta_window_maximize (window,
|
||||
(window->display->grab_resize_unmaximize & ~new_unmaximize));
|
||||
window->saved_rect = saved_rect;
|
||||
}
|
||||
}
|
||||
|
||||
window->display->grab_resize_unmaximize = new_unmaximize;
|
||||
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
|
||||
|
||||
/* Store the latest resize time, if we actually resized. */
|
||||
if (window->rect.width != old.width || window->rect.height != old.height)
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include <meta/common.h>
|
||||
#include <meta/types.h>
|
||||
#include "theme-private.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -69,8 +70,6 @@ typedef enum
|
||||
typedef struct _MetaFrames MetaFrames;
|
||||
typedef struct _MetaFramesClass MetaFramesClass;
|
||||
|
||||
typedef struct _MetaUIFrame MetaUIFrame;
|
||||
|
||||
struct _MetaUIFrame
|
||||
{
|
||||
MetaFrames *frames;
|
||||
|
@@ -115,7 +115,7 @@ struct _MetaFrameGeometry
|
||||
|
||||
/* used for a memset hack */
|
||||
#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
|
||||
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
|
||||
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
|
||||
|
||||
/* The button rects (if changed adjust memset hack) */
|
||||
MetaButtonSpace close_rect;
|
||||
|
@@ -121,7 +121,7 @@ meta_frame_layout_get_borders (const MetaFrameLayout *layout,
|
||||
}
|
||||
|
||||
int
|
||||
meta_theme_get_window_scaling_factor ()
|
||||
meta_theme_get_window_scaling_factor (void)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
34
src/wayland/meta-wayland-data-device-private.h
Normal file
34
src/wayland/meta-wayland-data-device-private.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND (meta_wayland_data_source_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
|
||||
meta_wayland_data_source_wayland,
|
||||
META, WAYLAND_DATA_SOURCE_WAYLAND,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */
|
@@ -31,24 +31,44 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-wayland-data-device-private.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-dnd-actor-private.h"
|
||||
|
||||
typedef struct
|
||||
struct _MetaWaylandDataOffer
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_listener source_destroy_listener;
|
||||
} MetaWaylandDataOffer;
|
||||
};
|
||||
|
||||
struct _MetaWaylandDataSource
|
||||
typedef struct _MetaWaylandDataSourcePrivate
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
};
|
||||
} MetaWaylandDataSourcePrivate;
|
||||
|
||||
typedef struct _MetaWaylandDataSourceWayland
|
||||
{
|
||||
MetaWaylandDataSource parent;
|
||||
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandDataSourceWayland;
|
||||
|
||||
GType meta_wayland_data_source_wayland_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
|
||||
|
||||
static void
|
||||
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@@ -56,6 +76,55 @@ unbind_resource (struct wl_resource *resource)
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
||||
const char *mime_type,
|
||||
int fd)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_has_target (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->has_target;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
|
||||
gboolean has_target)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->has_target = has_target;
|
||||
}
|
||||
|
||||
struct wl_array *
|
||||
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return &priv->mime_types;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_accept (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@@ -70,8 +139,9 @@ data_offer_accept (struct wl_client *client,
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
offer->source->has_target = mime_type != NULL;
|
||||
meta_wayland_data_source_target (offer->source, mime_type);
|
||||
meta_wayland_data_source_set_has_target (offer->source,
|
||||
mime_type != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,9 +152,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
wl_data_source_send_send (offer->source->resource, mime_type, fd);
|
||||
|
||||
close (fd);
|
||||
meta_wayland_data_source_send (offer->source, mime_type, fd);
|
||||
else
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -105,38 +175,34 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
wl_list_remove (&offer->source_destroy_listener.link);
|
||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||
(gpointer *)&offer->source);
|
||||
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_offer_data_source (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
offer = wl_container_of (listener, offer, source_destroy_listener);
|
||||
|
||||
offer->source = NULL;
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
char **p;
|
||||
|
||||
offer->source = source;
|
||||
offer->source_destroy_listener.notify = destroy_offer_data_source;
|
||||
|
||||
offer->resource = wl_resource_create (wl_resource_get_client (target), &wl_data_offer_interface, wl_resource_get_version (target), 0);
|
||||
wl_resource_set_implementation (offer->resource, &data_offer_interface, offer, destroy_data_offer);
|
||||
wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener);
|
||||
g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
|
||||
offer->resource = wl_resource_create (wl_resource_get_client (target),
|
||||
&wl_data_offer_interface,
|
||||
wl_resource_get_version (target), 0);
|
||||
wl_resource_set_implementation (offer->resource,
|
||||
&data_offer_interface,
|
||||
offer,
|
||||
destroy_data_offer);
|
||||
|
||||
wl_data_device_send_data_offer (target, offer->resource);
|
||||
|
||||
wl_array_for_each (p, &source->mime_types)
|
||||
wl_array_for_each (p, &priv->mime_types)
|
||||
wl_data_offer_send_offer (offer->resource, *p);
|
||||
|
||||
return offer->resource;
|
||||
@@ -147,12 +213,8 @@ data_source_offer (struct wl_client *client,
|
||||
struct wl_resource *resource, const char *type)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
|
||||
p = wl_array_add (&source->mime_types, sizeof *p);
|
||||
if (p)
|
||||
*p = strdup (type);
|
||||
if (!p || !*p)
|
||||
if (!meta_wayland_data_source_add_mime_type (source, type))
|
||||
wl_resource_post_no_memory (resource);
|
||||
}
|
||||
|
||||
@@ -181,7 +243,6 @@ struct _MetaWaylandDragGrab {
|
||||
struct wl_listener drag_icon_listener;
|
||||
|
||||
MetaWaylandDataSource *drag_data_source;
|
||||
struct wl_listener drag_data_source_listener;
|
||||
|
||||
ClutterActor *feedback_actor;
|
||||
|
||||
@@ -199,26 +260,20 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
|
||||
grab->drag_focus_data_device = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface)
|
||||
void
|
||||
meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *data_device_resource, *offer = NULL;
|
||||
struct wl_display *display;
|
||||
guint32 serial;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
if (drag_grab->drag_focus == surface)
|
||||
return;
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
if (drag_grab->drag_focus)
|
||||
{
|
||||
wl_data_device_send_leave (drag_grab->drag_focus_data_device);
|
||||
wl_list_remove (&drag_grab->drag_focus_listener.link);
|
||||
drag_grab->drag_focus_data_device = NULL;
|
||||
meta_wayland_surface_drag_dest_focus_out (drag_grab->drag_focus);
|
||||
drag_grab->drag_focus = NULL;
|
||||
}
|
||||
|
||||
@@ -232,25 +287,31 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
||||
if (!data_device_resource)
|
||||
return;
|
||||
|
||||
display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
if (drag_grab->drag_data_source && data_device_resource)
|
||||
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
|
||||
data_device_resource);
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
|
||||
wl_data_device_send_enter (data_device_resource, serial, surface->resource,
|
||||
sx, sy, offer);
|
||||
|
||||
drag_grab->drag_focus = surface;
|
||||
|
||||
drag_grab->drag_focus_data_device = data_device_resource;
|
||||
drag_grab->drag_focus_listener.notify = destroy_drag_focus;
|
||||
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
|
||||
|
||||
meta_wayland_surface_drag_dest_focus_in (drag_grab->drag_focus,
|
||||
offer ? wl_resource_get_user_data (offer) : NULL);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
return drag_grab->drag_focus;
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
|
||||
meta_wayland_drag_grab_set_focus (drag_grab, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -258,17 +319,9 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
{
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
|
||||
drag_grab->drag_focus,
|
||||
&sx, &sy);
|
||||
wl_data_device_send_motion (drag_grab->drag_focus_data_device,
|
||||
clutter_event_get_time (event),
|
||||
sx, sy);
|
||||
}
|
||||
if (drag_grab->drag_focus)
|
||||
meta_wayland_surface_drag_dest_motion (drag_grab->drag_focus, event);
|
||||
|
||||
if (drag_grab->drag_surface)
|
||||
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
@@ -278,6 +331,8 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
static void
|
||||
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
meta_wayland_drag_grab_set_focus (drag_grab, NULL);
|
||||
|
||||
if (drag_grab->drag_origin)
|
||||
{
|
||||
drag_grab->drag_origin = NULL;
|
||||
@@ -291,10 +346,9 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
}
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
{
|
||||
drag_grab->drag_data_source->has_target = FALSE;
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
}
|
||||
g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source),
|
||||
drag_grab_data_source_destroyed,
|
||||
drag_grab);
|
||||
|
||||
if (drag_grab->feedback_actor)
|
||||
{
|
||||
@@ -304,8 +358,6 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
|
||||
drag_grab->seat->data_device.current_grab = NULL;
|
||||
|
||||
drag_grab_focus (&drag_grab->generic, NULL);
|
||||
|
||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
||||
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
||||
}
|
||||
@@ -323,10 +375,9 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (drag_grab->drag_focus_data_device &&
|
||||
drag_grab->drag_data_source->has_target)
|
||||
if (meta_wayland_data_source_has_target (drag_grab->drag_data_source))
|
||||
{
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
@@ -355,23 +406,24 @@ destroy_data_device_origin (struct wl_listener *listener, void *data)
|
||||
|
||||
drag_grab->drag_origin = NULL;
|
||||
data_device_end_drag_grab (drag_grab);
|
||||
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_data_device_source (struct wl_listener *listener, void *data)
|
||||
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab =
|
||||
wl_container_of (listener, drag_grab, drag_data_source_listener);
|
||||
MetaWaylandDragGrab *drag_grab = data;
|
||||
|
||||
drag_grab->drag_data_source = NULL;
|
||||
data_device_end_drag_grab (drag_grab);
|
||||
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_data_device_icon (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab =
|
||||
wl_container_of (listener, drag_grab, drag_data_source_listener);
|
||||
wl_container_of (listener, drag_grab, drag_icon_listener);
|
||||
|
||||
drag_grab->drag_surface = NULL;
|
||||
|
||||
@@ -379,6 +431,76 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
|
||||
clutter_actor_remove_all_children (drag_grab->feedback_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
||||
struct wl_client *client,
|
||||
const MetaWaylandPointerGrabInterface *funcs,
|
||||
MetaWaylandSurface *surface,
|
||||
MetaWaylandDataSource *source,
|
||||
MetaWaylandSurface *icon_surface)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
ClutterPoint pos, stage_pos;
|
||||
|
||||
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
|
||||
drag_grab->generic.interface = funcs;
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
drag_grab->drag_origin = surface;
|
||||
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
||||
wl_resource_add_destroy_listener (surface->resource,
|
||||
&drag_grab->drag_origin_listener);
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &stage_pos.x, &stage_pos.y);
|
||||
drag_grab->drag_start_x = stage_pos.x;
|
||||
drag_grab->drag_start_y = stage_pos.y;
|
||||
|
||||
g_object_weak_ref (G_OBJECT (source),
|
||||
drag_grab_data_source_destroyed,
|
||||
drag_grab);
|
||||
|
||||
drag_grab->drag_data_source = source;
|
||||
meta_wayland_data_device_set_dnd_source (data_device,
|
||||
drag_grab->drag_data_source);
|
||||
|
||||
if (icon_surface)
|
||||
{
|
||||
drag_grab->drag_surface = icon_surface;
|
||||
|
||||
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
|
||||
wl_resource_add_destroy_listener (icon_surface->resource,
|
||||
&drag_grab->drag_icon_listener);
|
||||
|
||||
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
|
||||
drag_grab->drag_start_x,
|
||||
drag_grab->drag_start_y);
|
||||
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
clutter_actor_add_child (drag_grab->feedback_actor,
|
||||
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
|
||||
|
||||
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
pos.x, pos.y);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*) drag_grab);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
if (data_device->current_grab)
|
||||
data_device_end_drag_grab (data_device->current_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_start_drag (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@@ -388,9 +510,8 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandSurface *surface = NULL;
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
ClutterPoint pos;
|
||||
MetaWaylandSurface *surface = NULL, *icon_surface = NULL;
|
||||
MetaWaylandDataSource *drag_source = NULL;
|
||||
|
||||
if (origin_resource)
|
||||
surface = wl_resource_get_user_data (origin_resource);
|
||||
@@ -410,69 +531,28 @@ data_device_start_drag (struct wl_client *client,
|
||||
seat->pointer.grab != &seat->pointer.default_grab)
|
||||
return;
|
||||
|
||||
if (icon_resource)
|
||||
icon_surface = wl_resource_get_user_data (icon_resource);
|
||||
if (source_resource)
|
||||
drag_source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
if (icon_resource &&
|
||||
meta_wayland_surface_set_role (wl_resource_get_user_data (icon_resource),
|
||||
meta_wayland_surface_set_role (icon_surface,
|
||||
META_WAYLAND_SURFACE_ROLE_DND,
|
||||
resource,
|
||||
WL_DATA_DEVICE_ERROR_ROLE) != 0)
|
||||
return;
|
||||
|
||||
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
|
||||
drag_grab->generic.interface = &drag_grab_interface;
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
drag_grab->drag_origin = surface;
|
||||
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
||||
wl_resource_add_destroy_listener (origin_resource,
|
||||
&drag_grab->drag_origin_listener);
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &pos.x, &pos.y);
|
||||
drag_grab->drag_start_x = pos.x;
|
||||
drag_grab->drag_start_y = pos.y;
|
||||
|
||||
if (source_resource)
|
||||
{
|
||||
drag_grab->drag_data_source = wl_resource_get_user_data (source_resource);
|
||||
drag_grab->drag_data_source_listener.notify = destroy_data_device_source;
|
||||
wl_resource_add_destroy_listener (source_resource,
|
||||
&drag_grab->drag_data_source_listener);
|
||||
}
|
||||
|
||||
if (icon_resource)
|
||||
{
|
||||
drag_grab->drag_surface = wl_resource_get_user_data (icon_resource);
|
||||
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
|
||||
wl_resource_add_destroy_listener (icon_resource,
|
||||
&drag_grab->drag_icon_listener);
|
||||
|
||||
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
|
||||
drag_grab->drag_start_x,
|
||||
drag_grab->drag_start_y);
|
||||
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
clutter_actor_add_child (drag_grab->feedback_actor,
|
||||
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
pos.x, pos.y);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
|
||||
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
|
||||
meta_wayland_data_device_start_drag (data_device, client,
|
||||
&drag_grab_interface,
|
||||
surface, drag_source, icon_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
selection_data_source_destroyed (gpointer data, GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener);
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client = NULL;
|
||||
@@ -489,6 +569,190 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
|
||||
wl_data_source_send_send (source_wayland->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_target (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
|
||||
wl_data_source_send_target (source_wayland->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
|
||||
wl_data_source_send_cancelled (source_wayland->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_init (MetaWaylandDataSourceWayland *source_wayland)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_source_finalize;
|
||||
|
||||
data_source_class->send = meta_wayland_source_send;
|
||||
data_source_class->target = meta_wayland_source_target;
|
||||
data_source_class->cancel = meta_wayland_source_cancel;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
char **pos;
|
||||
|
||||
wl_array_for_each (pos, &priv->mime_types)
|
||||
g_free (*pos);
|
||||
wl_array_release (&priv->mime_types);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_init (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_array_init (&priv->mime_types);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_data_source_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface,
|
||||
MetaWaylandDataOffer *offer)
|
||||
{
|
||||
MetaWaylandDragGrab *grab = data_device->current_grab;
|
||||
struct wl_display *display;
|
||||
struct wl_client *client;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
if (!grab->drag_focus_data_device)
|
||||
return;
|
||||
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
display = wl_client_get_display (client);
|
||||
|
||||
grab->drag_focus_listener.notify = destroy_drag_focus;
|
||||
wl_resource_add_destroy_listener (grab->drag_focus_data_device,
|
||||
&grab->drag_focus_listener);
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
|
||||
surface, &sx, &sy);
|
||||
wl_data_device_send_enter (grab->drag_focus_data_device,
|
||||
wl_display_next_serial (display),
|
||||
surface->resource, sx, sy, offer->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_drag_dest_focus_out (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandDragGrab *grab = data_device->current_grab;
|
||||
|
||||
if (grab->drag_focus_data_device)
|
||||
wl_data_device_send_leave (grab->drag_focus_data_device);
|
||||
|
||||
wl_list_remove (&grab->drag_focus_listener.link);
|
||||
grab->drag_focus_data_device = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_drag_dest_motion (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandDragGrab *grab = data_device->current_grab;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer,
|
||||
grab->drag_focus,
|
||||
&sx, &sy);
|
||||
wl_data_device_send_motion (grab->drag_focus_data_device,
|
||||
clutter_event_get_time (event),
|
||||
sx, sy);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_drag_dest_drop (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandDragGrab *grab = data_device->current_grab;
|
||||
|
||||
wl_data_device_send_drop (grab->drag_focus_data_device);
|
||||
}
|
||||
|
||||
static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = {
|
||||
meta_wayland_drag_dest_focus_in,
|
||||
meta_wayland_drag_dest_focus_out,
|
||||
meta_wayland_drag_dest_motion,
|
||||
meta_wayland_drag_dest_drop
|
||||
};
|
||||
|
||||
const MetaWaylandDragDestFuncs *
|
||||
meta_wayland_data_device_get_drag_dest_funcs (void)
|
||||
{
|
||||
return &meta_wayland_drag_dest_funcs;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source)
|
||||
{
|
||||
if (data_device->dnd_data_source == source)
|
||||
return;
|
||||
|
||||
if (data_device->dnd_data_source)
|
||||
g_object_remove_weak_pointer (G_OBJECT (source),
|
||||
(gpointer *)&data_device->dnd_data_source);
|
||||
|
||||
data_device->dnd_data_source = source;
|
||||
g_object_add_weak_pointer (G_OBJECT (source),
|
||||
(gpointer *)&data_device->dnd_data_source);
|
||||
|
||||
wl_signal_emit (&data_device->dnd_ownership_signal, source);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
@@ -503,8 +767,10 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (data_device->selection_data_source)
|
||||
{
|
||||
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
|
||||
wl_list_remove (&data_device->selection_data_source_listener.link);
|
||||
meta_wayland_data_source_cancel (data_device->selection_data_source);
|
||||
g_object_weak_unref (G_OBJECT (data_device->selection_data_source),
|
||||
selection_data_source_destroyed,
|
||||
data_device);
|
||||
data_device->selection_data_source = NULL;
|
||||
}
|
||||
|
||||
@@ -531,9 +797,12 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (source)
|
||||
{
|
||||
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
|
||||
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
|
||||
g_object_weak_ref (G_OBJECT (source),
|
||||
selection_data_source_destroyed,
|
||||
data_device);
|
||||
}
|
||||
|
||||
wl_signal_emit (&data_device->selection_ownership_signal, source);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -545,10 +814,10 @@ data_device_set_selection (struct wl_client *client,
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
if (!source_resource)
|
||||
return;
|
||||
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
if (source_resource)
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
else
|
||||
source = NULL;
|
||||
|
||||
/* FIXME: Store serial and check against incoming serial here. */
|
||||
meta_wayland_data_device_set_selection (data_device, source, serial);
|
||||
@@ -569,26 +838,21 @@ static const struct wl_data_device_interface data_device_interface = {
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_array_for_each (p, &source->mime_types) free (*p);
|
||||
|
||||
wl_array_release (&source->mime_types);
|
||||
|
||||
g_slice_free (MetaWaylandDataSource, source);
|
||||
source->resource = NULL;
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
static void
|
||||
create_data_source (struct wl_client *client,
|
||||
struct wl_resource *resource, guint32 id)
|
||||
{
|
||||
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
|
||||
struct wl_resource *source_resource;
|
||||
|
||||
source->resource = wl_resource_create (client, &wl_data_source_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (source->resource, &data_source_interface, source, destroy_data_source);
|
||||
|
||||
wl_array_init (&source->mime_types);
|
||||
source_resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
meta_wayland_data_source_wayland_new (source_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -632,6 +896,8 @@ void
|
||||
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
wl_signal_init (&data_device->selection_ownership_signal);
|
||||
wl_signal_init (&data_device->dnd_ownership_signal);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -656,6 +922,8 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
else
|
||||
wl_data_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -683,3 +951,52 @@ meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
gchar **p;
|
||||
|
||||
wl_array_for_each (p, &priv->mime_types)
|
||||
{
|
||||
if (g_strcmp0 (mime_type, *p) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND, NULL);
|
||||
|
||||
source_wayland->resource = resource;
|
||||
wl_resource_set_implementation (resource, &data_source_interface,
|
||||
source_wayland, destroy_data_source);
|
||||
|
||||
return META_WAYLAND_DATA_SOURCE (source_wayland);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
gchar **pos;
|
||||
|
||||
pos = wl_array_add (&priv->mime_types, sizeof (*pos));
|
||||
|
||||
if (pos)
|
||||
{
|
||||
*pos = g_strdup (mime_type);
|
||||
return *pos != NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -24,20 +24,44 @@
|
||||
#define META_WAYLAND_DATA_DEVICE_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||
typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
META, WAYLAND_DATA_SOURCE, GObject);
|
||||
|
||||
struct _MetaWaylandDataSourceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* send) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd);
|
||||
void (* target) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
void (* cancel) (MetaWaylandDataSource *source);
|
||||
};
|
||||
|
||||
struct _MetaWaylandDataDevice
|
||||
{
|
||||
uint32_t selection_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
MetaWaylandDataSource *dnd_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
|
||||
struct wl_signal selection_ownership_signal;
|
||||
struct wl_signal dnd_ownership_signal;
|
||||
};
|
||||
|
||||
GType meta_wayland_data_source_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
|
||||
@@ -48,4 +72,45 @@ gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_de
|
||||
MetaWaylandSurface *surface);
|
||||
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
|
||||
|
||||
void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial);
|
||||
|
||||
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
|
||||
gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
|
||||
struct wl_array *
|
||||
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source);
|
||||
|
||||
gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
|
||||
gboolean has_target);
|
||||
|
||||
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd);
|
||||
|
||||
const MetaWaylandDragDestFuncs *
|
||||
meta_wayland_data_device_get_drag_dest_funcs (void);
|
||||
|
||||
void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device,
|
||||
struct wl_client *client,
|
||||
const MetaWaylandPointerGrabInterface *funcs,
|
||||
MetaWaylandSurface *surface,
|
||||
MetaWaylandDataSource *source,
|
||||
MetaWaylandSurface *icon_surface);
|
||||
|
||||
void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device);
|
||||
|
||||
void meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
|
||||
MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface *
|
||||
meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_H */
|
||||
|
@@ -32,7 +32,7 @@
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
MetaOutput *output;
|
||||
MetaMonitorInfo *monitor_info;
|
||||
struct wl_global *global;
|
||||
int x, y;
|
||||
enum wl_output_transform transform;
|
||||
@@ -56,9 +56,10 @@ bind_output (struct wl_client *client,
|
||||
guint32 id)
|
||||
{
|
||||
MetaWaylandOutput *wayland_output = data;
|
||||
MetaOutput *output = wayland_output->output;
|
||||
MetaMonitorInfo *monitor_info = wayland_output->monitor_info;
|
||||
struct wl_resource *resource;
|
||||
guint mode_flags;
|
||||
MetaOutput *output = monitor_info->outputs[0];
|
||||
|
||||
resource = wl_resource_create (client, &wl_output_interface, version, id);
|
||||
wayland_output->resources = g_list_prepend (wayland_output->resources, resource);
|
||||
@@ -66,17 +67,17 @@ bind_output (struct wl_client *client,
|
||||
wl_resource_set_user_data (resource, wayland_output);
|
||||
wl_resource_set_destructor (resource, output_resource_destroy);
|
||||
|
||||
meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
|
||||
output, output->name,
|
||||
output->crtc->rect.x, output->crtc->rect.y,
|
||||
output->crtc->rect.width, output->crtc->rect.height,
|
||||
output->crtc->current_mode->refresh_rate);
|
||||
meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f\n",
|
||||
monitor_info, output->name,
|
||||
monitor_info->rect.x, monitor_info->rect.y,
|
||||
monitor_info->rect.width, monitor_info->rect.height,
|
||||
monitor_info->refresh_rate);
|
||||
|
||||
wl_output_send_geometry (resource,
|
||||
(int)output->crtc->rect.x,
|
||||
(int)output->crtc->rect.y,
|
||||
output->width_mm,
|
||||
output->height_mm,
|
||||
(int)monitor_info->rect.x,
|
||||
(int)monitor_info->rect.y,
|
||||
monitor_info->width_mm,
|
||||
monitor_info->height_mm,
|
||||
/* Cogl values reflect XRandR values,
|
||||
and so does wayland */
|
||||
output->subpixel_order,
|
||||
@@ -92,9 +93,9 @@ bind_output (struct wl_client *client,
|
||||
|
||||
wl_output_send_mode (resource,
|
||||
mode_flags,
|
||||
(int)output->crtc->current_mode->width,
|
||||
(int)output->crtc->current_mode->height,
|
||||
(int)output->crtc->current_mode->refresh_rate);
|
||||
(int)monitor_info->rect.width,
|
||||
(int)monitor_info->rect.height,
|
||||
(int)monitor_info->refresh_rate);
|
||||
|
||||
if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
|
||||
wl_output_send_scale (resource, output->scale);
|
||||
@@ -128,14 +129,13 @@ wl_output_transform_from_meta_monitor_transform (MetaMonitorTransform transform)
|
||||
|
||||
static void
|
||||
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
MetaOutput *output)
|
||||
MetaMonitorInfo *monitor_info)
|
||||
{
|
||||
GList *iter;
|
||||
guint mode_flags;
|
||||
MetaOutput *output = monitor_info->outputs[0];
|
||||
enum wl_output_transform wl_transform = wl_output_transform_from_meta_monitor_transform (output->crtc->transform);
|
||||
|
||||
g_assert (output->crtc->current_mode != NULL);
|
||||
|
||||
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
||||
if (output->crtc->current_mode == output->preferred_mode)
|
||||
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||
@@ -144,15 +144,15 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
{
|
||||
struct wl_resource *resource = iter->data;
|
||||
|
||||
if (wayland_output->x != output->crtc->rect.x ||
|
||||
wayland_output->y != output->crtc->rect.y ||
|
||||
if (wayland_output->x != monitor_info->rect.x ||
|
||||
wayland_output->y != monitor_info->rect.y ||
|
||||
wayland_output->transform != wl_transform)
|
||||
{
|
||||
wl_output_send_geometry (resource,
|
||||
(int)output->crtc->rect.x,
|
||||
(int)output->crtc->rect.y,
|
||||
output->width_mm,
|
||||
output->height_mm,
|
||||
(int)monitor_info->rect.x,
|
||||
(int)monitor_info->rect.y,
|
||||
monitor_info->width_mm,
|
||||
monitor_info->height_mm,
|
||||
output->subpixel_order,
|
||||
output->vendor,
|
||||
output->product,
|
||||
@@ -161,16 +161,16 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
|
||||
wl_output_send_mode (resource,
|
||||
mode_flags,
|
||||
(int)output->crtc->current_mode->width,
|
||||
(int)output->crtc->current_mode->height,
|
||||
(int)output->crtc->current_mode->refresh_rate);
|
||||
(int)monitor_info->rect.width,
|
||||
(int)monitor_info->rect.height,
|
||||
(int)monitor_info->refresh_rate);
|
||||
}
|
||||
|
||||
/* It's very important that we change the output pointer here, as
|
||||
the old structure is about to be freed by MetaMonitorManager */
|
||||
wayland_output->output = output;
|
||||
wayland_output->x = output->crtc->rect.x;
|
||||
wayland_output->y = output->crtc->rect.y;
|
||||
wayland_output->monitor_info = monitor_info;
|
||||
wayland_output->x = monitor_info->rect.x;
|
||||
wayland_output->y = monitor_info->rect.y;
|
||||
wayland_output->transform = wl_transform;
|
||||
}
|
||||
|
||||
@@ -178,30 +178,26 @@ static GHashTable *
|
||||
meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||
MetaMonitorManager *monitors)
|
||||
{
|
||||
MetaOutput *outputs;
|
||||
unsigned int i, n_outputs;
|
||||
unsigned int i;
|
||||
GHashTable *new_table;
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
unsigned int n_monitor_infos;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (monitors, &n_outputs);
|
||||
monitor_infos = meta_monitor_manager_get_monitor_infos (monitors, &n_monitor_infos);
|
||||
new_table = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
for (i = 0; i < n_monitor_infos; i++)
|
||||
{
|
||||
MetaOutput *output = &outputs[i];
|
||||
MetaMonitorInfo *info = &monitor_infos[i];
|
||||
MetaWaylandOutput *wayland_output;
|
||||
|
||||
/* wayland does not expose disabled outputs */
|
||||
if (output->crtc == NULL)
|
||||
{
|
||||
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
if (info->winsys_id == 0)
|
||||
continue;
|
||||
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (info->winsys_id));
|
||||
|
||||
if (wayland_output)
|
||||
{
|
||||
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (info->winsys_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -212,8 +208,8 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||
wayland_output, bind_output);
|
||||
}
|
||||
|
||||
wayland_output_update_for_output (wayland_output, output);
|
||||
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->winsys_id), wayland_output);
|
||||
wayland_output_update_for_output (wayland_output, info);
|
||||
g_hash_table_insert (new_table, GSIZE_TO_POINTER (info->winsys_id), wayland_output);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (compositor->outputs);
|
||||
|
@@ -339,8 +339,6 @@ handle_button_event (MetaWaylandPointer *pointer,
|
||||
{
|
||||
gboolean implicit_grab;
|
||||
|
||||
notify_motion (pointer, event);
|
||||
|
||||
implicit_grab = (event->type == CLUTTER_BUTTON_PRESS) && (pointer->button_count == 1);
|
||||
if (implicit_grab)
|
||||
{
|
||||
@@ -363,8 +361,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
|
||||
struct wl_list *l;
|
||||
wl_fixed_t x_value = 0, y_value = 0;
|
||||
|
||||
notify_motion (pointer, event);
|
||||
|
||||
if (clutter_event_is_pointer_emulated (event))
|
||||
return;
|
||||
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
|
||||
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_list link;
|
||||
@@ -52,6 +54,8 @@ typedef struct
|
||||
char *display_name;
|
||||
|
||||
GMainLoop *init_loop;
|
||||
|
||||
MetaXWaylandSelection *selection_data;
|
||||
} MetaXWaylandManager;
|
||||
|
||||
struct _MetaWaylandCompositor
|
||||
|
@@ -52,6 +52,7 @@
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-xwayland-private.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -485,6 +486,9 @@ apply_pending_state (MetaWaylandSurface *surface,
|
||||
|
||||
if (pending->newly_attached)
|
||||
{
|
||||
if (!surface->buffer && surface->window)
|
||||
meta_window_queue (surface->window, META_QUEUE_CALC_SHOWING);
|
||||
|
||||
surface_set_buffer (surface, pending->buffer);
|
||||
|
||||
if (pending->buffer)
|
||||
@@ -748,12 +752,23 @@ sync_reactive (MetaWaylandSurface *surface)
|
||||
surface_should_be_reactive (surface));
|
||||
}
|
||||
|
||||
static void
|
||||
sync_drag_dest_funcs (MetaWaylandSurface *surface)
|
||||
{
|
||||
if (surface->window &&
|
||||
surface->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
surface->dnd.funcs = meta_xwayland_selection_get_drag_dest_funcs ();
|
||||
else
|
||||
surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs ();
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
|
||||
MetaWindow *window)
|
||||
{
|
||||
surface->window = window;
|
||||
sync_reactive (surface);
|
||||
sync_drag_dest_funcs (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -816,6 +831,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
|
||||
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
|
||||
|
||||
sync_drag_dest_funcs (surface);
|
||||
|
||||
pending_state_init (&surface->pending);
|
||||
return surface;
|
||||
}
|
||||
@@ -1259,8 +1276,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
|
||||
window = meta_window_wayland_new (display, surface);
|
||||
meta_window_move_frame (window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
parent_surf->window->buffer_rect.x + x,
|
||||
parent_surf->window->buffer_rect.y + y);
|
||||
window->showing_for_first_time = FALSE;
|
||||
window->placed = TRUE;
|
||||
|
||||
@@ -1525,6 +1542,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWindow *window;
|
||||
|
||||
if (surface->wl_shell_surface != NULL)
|
||||
{
|
||||
@@ -1542,6 +1560,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
|
||||
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
}
|
||||
|
||||
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
|
||||
@@ -2043,3 +2064,41 @@ meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface,
|
||||
MetaWaylandDataOffer *offer)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
|
||||
surface->dnd.funcs->focus_in (data_device, surface, offer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
|
||||
surface->dnd.funcs->motion (data_device, surface, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
|
||||
surface->dnd.funcs->focus_out (data_device, surface);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
|
||||
surface->dnd.funcs->drop (data_device, surface);
|
||||
}
|
||||
|
@@ -71,6 +71,20 @@ typedef struct
|
||||
gboolean has_new_geometry;
|
||||
} MetaWaylandPendingState;
|
||||
|
||||
struct _MetaWaylandDragDestFuncs
|
||||
{
|
||||
void (* focus_in) (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface,
|
||||
MetaWaylandDataOffer *offer);
|
||||
void (* focus_out) (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface);
|
||||
void (* motion) (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event);
|
||||
void (* drop) (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface);
|
||||
};
|
||||
|
||||
struct _MetaWaylandSurface
|
||||
{
|
||||
/* Generic stuff */
|
||||
@@ -87,6 +101,10 @@ struct _MetaWaylandSurface
|
||||
int32_t offset_x, offset_y;
|
||||
GList *subsurfaces;
|
||||
|
||||
struct {
|
||||
const MetaWaylandDragDestFuncs *funcs;
|
||||
} dnd;
|
||||
|
||||
/* All the pending state that wl_surface.commit will apply. */
|
||||
MetaWaylandPendingState pending;
|
||||
|
||||
@@ -161,4 +179,12 @@ void meta_wayland_surface_delete (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
|
||||
|
||||
/* Drag dest functions */
|
||||
void meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface,
|
||||
MetaWaylandDataOffer *offer);
|
||||
void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
|
||||
|
||||
#endif
|
||||
|
@@ -30,7 +30,8 @@ typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab;
|
||||
typedef struct _MetaWaylandPopup MetaWaylandPopup;
|
||||
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
|
||||
typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
||||
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
|
||||
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||
|
||||
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
|
||||
|
@@ -34,4 +34,11 @@ meta_xwayland_complete_init (void);
|
||||
void
|
||||
meta_xwayland_stop (MetaXWaylandManager *manager);
|
||||
|
||||
/* wl_data_device/X11 selection interoperation */
|
||||
void meta_xwayland_init_selection (void);
|
||||
void meta_xwayland_shutdown_selection (void);
|
||||
gboolean meta_xwayland_selection_handle_event (XEvent *xevent);
|
||||
|
||||
const MetaWaylandDragDestFuncs * meta_xwayland_selection_get_drag_dest_funcs (void);
|
||||
|
||||
#endif /* META_XWAYLAND_PRIVATE_H */
|
||||
|
34
src/wayland/meta-xwayland-selection-private.h
Normal file
34
src/wayland/meta-xwayland-selection-private.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef META_XWAYLAND_SELECTION_PRIVATE_H
|
||||
#define META_XWAYLAND_SELECTION_PRIVATE_H
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND (meta_wayland_data_source_xwayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceXWayland,
|
||||
meta_wayland_data_source_xwayland,
|
||||
META, WAYLAND_DATA_SOURCE_XWAYLAND,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#endif /* META_XWAYLAND_SELECTION_PRIVATE_H */
|
1577
src/wayland/meta-xwayland-selection.c
Normal file
1577
src/wayland/meta-xwayland-selection.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -522,6 +522,8 @@ meta_xwayland_complete_init (void)
|
||||
we won't reset the tty).
|
||||
*/
|
||||
XSetIOErrorHandler (x_io_error);
|
||||
|
||||
meta_xwayland_init_selection ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -529,6 +531,8 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
|
||||
{
|
||||
char path[256];
|
||||
|
||||
meta_xwayland_shutdown_selection ();
|
||||
|
||||
snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
|
||||
unlink (path);
|
||||
|
||||
|
@@ -1,680 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Asynchronous X property getting hack */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
* Copyright (C) 1986, 1998 The Open Group
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of The Open Group shall not be
|
||||
* used in advertising or otherwise to promote the sale, use or other dealings
|
||||
* in this Software without prior written authorization from The Open Group.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#undef DEBUG_SPEW
|
||||
#ifdef DEBUG_SPEW
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "async-getprop.h"
|
||||
|
||||
#define NEED_REPLIES
|
||||
#include <X11/Xlibint.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
typedef struct _ListNode ListNode;
|
||||
typedef struct _AgPerDisplayData AgPerDisplayData;
|
||||
|
||||
struct _ListNode
|
||||
{
|
||||
ListNode *next;
|
||||
};
|
||||
|
||||
struct _AgGetPropertyTask
|
||||
{
|
||||
ListNode node;
|
||||
|
||||
AgPerDisplayData *dd;
|
||||
Window window;
|
||||
Atom property;
|
||||
|
||||
unsigned long request_seq;
|
||||
int error;
|
||||
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
|
||||
unsigned long n_items;
|
||||
unsigned long bytes_after;
|
||||
char *data;
|
||||
|
||||
Bool have_reply;
|
||||
};
|
||||
|
||||
struct _AgPerDisplayData
|
||||
{
|
||||
ListNode node;
|
||||
_XAsyncHandler async;
|
||||
|
||||
Display *display;
|
||||
ListNode *pending_tasks;
|
||||
ListNode *pending_tasks_tail;
|
||||
ListNode *completed_tasks;
|
||||
ListNode *completed_tasks_tail;
|
||||
int n_tasks_pending;
|
||||
int n_tasks_completed;
|
||||
};
|
||||
|
||||
static ListNode *display_datas = NULL;
|
||||
static ListNode *display_datas_tail = NULL;
|
||||
|
||||
static void
|
||||
append_to_list (ListNode **head,
|
||||
ListNode **tail,
|
||||
ListNode *task)
|
||||
{
|
||||
task->next = NULL;
|
||||
|
||||
if (*tail == NULL)
|
||||
{
|
||||
assert (*head == NULL);
|
||||
*head = task;
|
||||
*tail = task;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*tail)->next = task;
|
||||
*tail = task;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_from_list (ListNode **head,
|
||||
ListNode **tail,
|
||||
ListNode *task)
|
||||
{
|
||||
ListNode *prev;
|
||||
ListNode *node;
|
||||
|
||||
prev = NULL;
|
||||
node = *head;
|
||||
while (node != NULL)
|
||||
{
|
||||
if (node == task)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = node->next;
|
||||
else
|
||||
*head = node->next;
|
||||
|
||||
if (node == *tail)
|
||||
*tail = prev;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prev = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
/* can't remove what's not there */
|
||||
assert (node != NULL);
|
||||
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
move_to_completed (AgPerDisplayData *dd,
|
||||
AgGetPropertyTask *task)
|
||||
{
|
||||
remove_from_list (&dd->pending_tasks,
|
||||
&dd->pending_tasks_tail,
|
||||
&task->node);
|
||||
|
||||
append_to_list (&dd->completed_tasks,
|
||||
&dd->completed_tasks_tail,
|
||||
&task->node);
|
||||
|
||||
dd->n_tasks_pending -= 1;
|
||||
dd->n_tasks_completed += 1;
|
||||
}
|
||||
|
||||
static AgGetPropertyTask*
|
||||
find_pending_by_request_sequence (AgPerDisplayData *dd,
|
||||
unsigned long request_seq)
|
||||
{
|
||||
ListNode *node;
|
||||
|
||||
/* if the sequence is after our last pending task, we
|
||||
* aren't going to find a match
|
||||
*/
|
||||
{
|
||||
AgGetPropertyTask *task = (AgGetPropertyTask*) dd->pending_tasks_tail;
|
||||
if (task != NULL)
|
||||
{
|
||||
if (task->request_seq < request_seq)
|
||||
return NULL;
|
||||
else if (task->request_seq == request_seq)
|
||||
return task; /* why not check this */
|
||||
}
|
||||
}
|
||||
|
||||
/* Generally we should get replies in the order we sent
|
||||
* requests, so we should usually be using the task
|
||||
* at the head of the list, if we use any task at all.
|
||||
* I'm not sure this is 100% guaranteed, if it is,
|
||||
* it would be a big speedup.
|
||||
*/
|
||||
|
||||
node = dd->pending_tasks;
|
||||
while (node != NULL)
|
||||
{
|
||||
AgGetPropertyTask *task = (AgGetPropertyTask*) node;
|
||||
|
||||
if (task->request_seq == request_seq)
|
||||
return task;
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Bool
|
||||
async_get_property_handler (Display *dpy,
|
||||
xReply *rep,
|
||||
char *buf,
|
||||
int len,
|
||||
XPointer data)
|
||||
{
|
||||
xGetPropertyReply replbuf;
|
||||
xGetPropertyReply *reply;
|
||||
AgGetPropertyTask *task;
|
||||
AgPerDisplayData *dd;
|
||||
int bytes_read;
|
||||
|
||||
dd = (AgPerDisplayData*) data;
|
||||
|
||||
#if 0
|
||||
printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__,
|
||||
dpy->last_request_read, len);
|
||||
#endif
|
||||
|
||||
task = find_pending_by_request_sequence (dd, dpy->last_request_read);
|
||||
|
||||
if (task == NULL)
|
||||
return False;
|
||||
|
||||
assert (dpy->last_request_read == task->request_seq);
|
||||
|
||||
task->have_reply = True;
|
||||
move_to_completed (dd, task);
|
||||
|
||||
/* read bytes so far */
|
||||
bytes_read = SIZEOF (xReply);
|
||||
|
||||
if (rep->generic.type == X_Error)
|
||||
{
|
||||
xError errbuf;
|
||||
|
||||
task->error = rep->error.errorCode;
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n",
|
||||
__FUNCTION__, task->error, (SIZEOF (xError) - bytes_read),
|
||||
rep->generic.length);
|
||||
#endif
|
||||
|
||||
/* We return True (meaning we consumed the reply)
|
||||
* because otherwise it would invoke the X error handler,
|
||||
* and an async API is useless if you have to synchronously
|
||||
* trap X errors. Also GetProperty can always fail, pretty
|
||||
* much, so trapping errors is always what you want.
|
||||
*
|
||||
* We have to eat all the error reply data here.
|
||||
* (kind of a charade as we know sizeof(xError) == sizeof(xReply))
|
||||
*
|
||||
* Passing discard = True seems to break things; I don't understand
|
||||
* why, because there should be no extra data in an error reply,
|
||||
* right?
|
||||
*/
|
||||
_XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
|
||||
(SIZEOF (xError) - bytes_read) >> 2, /* in 32-bit words */
|
||||
False); /* really seems like it should be True */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: already read %d bytes reading %d more for total of %d; generic.length = %ld\n",
|
||||
__FUNCTION__, bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
|
||||
SIZEOF (xGetPropertyReply), rep->generic.length);
|
||||
#endif
|
||||
|
||||
/* (kind of a silly as we know sizeof(xGetPropertyReply) == sizeof(xReply)) */
|
||||
reply = (xGetPropertyReply *)
|
||||
_XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len,
|
||||
(SIZEOF (xGetPropertyReply) - bytes_read) >> 2, /* in 32-bit words */
|
||||
False); /* False means expecting more data to follow,
|
||||
* don't eat the rest of the reply
|
||||
*/
|
||||
|
||||
bytes_read = SIZEOF (xGetPropertyReply);
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: have reply propertyType = %ld format = %d n_items = %ld\n",
|
||||
__FUNCTION__, reply->propertyType, reply->format, reply->nItems);
|
||||
#endif
|
||||
|
||||
assert (task->data == NULL);
|
||||
|
||||
/* This is all copied from XGetWindowProperty(). Not sure we should
|
||||
* LockDisplay(). Not sure I'm passing the right args to
|
||||
* XGetAsyncData(). Not sure about a lot of things.
|
||||
*/
|
||||
|
||||
/* LockDisplay (dpy); */
|
||||
|
||||
if (reply->propertyType != None)
|
||||
{
|
||||
long nbytes, netbytes;
|
||||
|
||||
/* this alignment macro from orbit2 */
|
||||
#define ALIGN_VALUE(this, boundary) \
|
||||
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
|
||||
|
||||
switch (reply->format)
|
||||
{
|
||||
/*
|
||||
* One extra byte is malloced than is needed to contain the property
|
||||
* data, but this last byte is null terminated and convenient for
|
||||
* returning string properties, so the client doesn't then have to
|
||||
* recopy the string to make it null terminated.
|
||||
*/
|
||||
case 8:
|
||||
nbytes = reply->nItems;
|
||||
/* there's padding to word boundary */
|
||||
netbytes = ALIGN_VALUE (nbytes, 4);
|
||||
if (nbytes + 1 > 0 &&
|
||||
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: already read %d bytes using %ld, more eating %ld more\n",
|
||||
__FUNCTION__, bytes_read, nbytes, netbytes);
|
||||
#endif
|
||||
/* _XReadPad (dpy, (char *) task->data, netbytes); */
|
||||
_XGetAsyncData (dpy, task->data, buf, len,
|
||||
bytes_read, nbytes,
|
||||
netbytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
nbytes = reply->nItems * sizeof (short);
|
||||
netbytes = reply->nItems << 1;
|
||||
netbytes = ALIGN_VALUE (netbytes, 4); /* align to word boundary */
|
||||
if (nbytes + 1 > 0 &&
|
||||
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
|
||||
__FUNCTION__, bytes_read, nbytes, netbytes);
|
||||
#endif
|
||||
/* _XRead16Pad (dpy, (short *) task->data, netbytes); */
|
||||
_XGetAsyncData (dpy, task->data, buf, len,
|
||||
bytes_read, nbytes, netbytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
/* NOTE buffer is in longs to match XGetWindowProperty() */
|
||||
nbytes = reply->nItems * sizeof (long);
|
||||
netbytes = reply->nItems << 2; /* wire size is always 32 bits though */
|
||||
if (nbytes + 1 > 0 &&
|
||||
(task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
|
||||
__FUNCTION__, bytes_read, nbytes, netbytes);
|
||||
#endif
|
||||
|
||||
/* We have to copy the XGetWindowProperty() crackrock
|
||||
* and get format 32 as long even on 64-bit platforms.
|
||||
*/
|
||||
if (sizeof (long) == 8)
|
||||
{
|
||||
char *netdata;
|
||||
char *lptr;
|
||||
char *end_lptr;
|
||||
|
||||
/* Store the 32-bit values in the end of the array */
|
||||
netdata = task->data + nbytes / 2;
|
||||
|
||||
_XGetAsyncData (dpy, netdata, buf, len,
|
||||
bytes_read, netbytes,
|
||||
netbytes);
|
||||
|
||||
/* Now move the 32-bit values to the front */
|
||||
|
||||
lptr = task->data;
|
||||
end_lptr = task->data + nbytes;
|
||||
while (lptr != end_lptr)
|
||||
{
|
||||
*(long*) lptr = *(CARD32*) netdata;
|
||||
lptr += sizeof (long);
|
||||
netdata += sizeof (CARD32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Here the wire format matches our actual format */
|
||||
_XGetAsyncData (dpy, task->data, buf, len,
|
||||
bytes_read, netbytes,
|
||||
netbytes);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* This part of the code should never be reached. If it is,
|
||||
* the server sent back a property with an invalid format.
|
||||
* This is a BadImplementation error.
|
||||
*
|
||||
* However this async GetProperty API doesn't report errors
|
||||
* via the standard X mechanism, so don't do anything about
|
||||
* it, other than store it in task->error.
|
||||
*/
|
||||
{
|
||||
#if 0
|
||||
xError error;
|
||||
#endif
|
||||
|
||||
task->error = BadImplementation;
|
||||
|
||||
#if 0
|
||||
error.sequenceNumber = task->request_seq;
|
||||
error.type = X_Error;
|
||||
error.majorCode = X_GetProperty;
|
||||
error.minorCode = 0;
|
||||
error.errorCode = BadImplementation;
|
||||
|
||||
_XError (dpy, &error);
|
||||
#endif
|
||||
}
|
||||
|
||||
nbytes = netbytes = 0L;
|
||||
break;
|
||||
}
|
||||
|
||||
if (task->data == NULL)
|
||||
{
|
||||
task->error = BadAlloc;
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: already read %d bytes eating %ld\n",
|
||||
__FUNCTION__, bytes_read, netbytes);
|
||||
#endif
|
||||
/* _XEatData (dpy, (unsigned long) netbytes); */
|
||||
_XGetAsyncData (dpy, NULL, buf, len,
|
||||
bytes_read, 0, netbytes);
|
||||
|
||||
/* UnlockDisplay (dpy); */
|
||||
return BadAlloc; /* not Success */
|
||||
}
|
||||
|
||||
(task->data)[nbytes] = '\0';
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%s: have data\n", __FUNCTION__);
|
||||
#endif
|
||||
|
||||
task->actual_type = reply->propertyType;
|
||||
task->actual_format = reply->format;
|
||||
task->n_items = reply->nItems;
|
||||
task->bytes_after = reply->bytesAfter;
|
||||
|
||||
/* UnlockDisplay (dpy); */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static AgPerDisplayData*
|
||||
get_display_data (Display *display,
|
||||
Bool create)
|
||||
{
|
||||
ListNode *node;
|
||||
AgPerDisplayData *dd;
|
||||
|
||||
node = display_datas;
|
||||
while (node != NULL)
|
||||
{
|
||||
dd = (AgPerDisplayData*) node;
|
||||
|
||||
if (dd->display == display)
|
||||
return dd;
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (!create)
|
||||
return NULL;
|
||||
|
||||
dd = Xcalloc (1, sizeof (AgPerDisplayData));
|
||||
if (dd == NULL)
|
||||
return NULL;
|
||||
|
||||
dd->display = display;
|
||||
dd->async.next = display->async_handlers;
|
||||
dd->async.handler = async_get_property_handler;
|
||||
dd->async.data = (XPointer) dd;
|
||||
dd->display->async_handlers = &dd->async;
|
||||
|
||||
append_to_list (&display_datas,
|
||||
&display_datas_tail,
|
||||
&dd->node);
|
||||
|
||||
return dd;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_free_display_data (AgPerDisplayData *dd)
|
||||
{
|
||||
if (dd->pending_tasks == NULL &&
|
||||
dd->completed_tasks == NULL)
|
||||
{
|
||||
DeqAsyncHandler (dd->display, &dd->async);
|
||||
remove_from_list (&display_datas, &display_datas_tail,
|
||||
&dd->node);
|
||||
XFree (dd);
|
||||
}
|
||||
}
|
||||
|
||||
AgGetPropertyTask*
|
||||
ag_task_create (Display *dpy,
|
||||
Window window,
|
||||
Atom property,
|
||||
long offset,
|
||||
long length,
|
||||
Bool delete,
|
||||
Atom req_type)
|
||||
{
|
||||
AgGetPropertyTask *task;
|
||||
xGetPropertyReq *req;
|
||||
AgPerDisplayData *dd;
|
||||
|
||||
/* Fire up our request */
|
||||
LockDisplay (dpy);
|
||||
|
||||
dd = get_display_data (dpy, True);
|
||||
if (dd == NULL)
|
||||
{
|
||||
UnlockDisplay (dpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GetReq (GetProperty, req);
|
||||
req->window = window;
|
||||
req->property = property;
|
||||
req->type = req_type;
|
||||
req->delete = delete;
|
||||
req->longOffset = offset;
|
||||
req->longLength = length;
|
||||
|
||||
/* Queue up our async task */
|
||||
task = Xcalloc (1, sizeof (AgGetPropertyTask));
|
||||
if (task == NULL)
|
||||
{
|
||||
UnlockDisplay (dpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->dd = dd;
|
||||
task->window = window;
|
||||
task->property = property;
|
||||
task->request_seq = dpy->request;
|
||||
|
||||
append_to_list (&dd->pending_tasks,
|
||||
&dd->pending_tasks_tail,
|
||||
&task->node);
|
||||
dd->n_tasks_pending += 1;
|
||||
|
||||
UnlockDisplay (dpy);
|
||||
|
||||
SyncHandle ();
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
static void
|
||||
free_task (AgGetPropertyTask *task)
|
||||
{
|
||||
remove_from_list (&task->dd->completed_tasks,
|
||||
&task->dd->completed_tasks_tail,
|
||||
&task->node);
|
||||
task->dd->n_tasks_completed -= 1;
|
||||
maybe_free_display_data (task->dd);
|
||||
XFree (task);
|
||||
}
|
||||
|
||||
Status
|
||||
ag_task_get_reply_and_free (AgGetPropertyTask *task,
|
||||
Atom *actual_type,
|
||||
int *actual_format,
|
||||
unsigned long *nitems,
|
||||
unsigned long *bytesafter,
|
||||
unsigned char **prop)
|
||||
{
|
||||
Display *dpy;
|
||||
|
||||
*prop = NULL;
|
||||
|
||||
dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */
|
||||
|
||||
if (task->error != Success)
|
||||
{
|
||||
Status s = task->error;
|
||||
|
||||
free_task (task);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!task->have_reply)
|
||||
{
|
||||
free_task (task);
|
||||
|
||||
return BadAlloc; /* not Success */
|
||||
}
|
||||
|
||||
*actual_type = task->actual_type;
|
||||
*actual_format = task->actual_format;
|
||||
*nitems = task->n_items;
|
||||
*bytesafter = task->bytes_after;
|
||||
|
||||
*prop = (unsigned char*) task->data; /* pass out ownership of task->data */
|
||||
|
||||
SyncHandle ();
|
||||
|
||||
free_task (task);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
Bool
|
||||
ag_task_have_reply (AgGetPropertyTask *task)
|
||||
{
|
||||
return task->have_reply;
|
||||
}
|
||||
|
||||
Atom
|
||||
ag_task_get_property (AgGetPropertyTask *task)
|
||||
{
|
||||
return task->property;
|
||||
}
|
||||
|
||||
Window
|
||||
ag_task_get_window (AgGetPropertyTask *task)
|
||||
{
|
||||
return task->window;
|
||||
}
|
||||
|
||||
Display*
|
||||
ag_task_get_display (AgGetPropertyTask *task)
|
||||
{
|
||||
return task->dd->display;
|
||||
}
|
||||
|
||||
AgGetPropertyTask*
|
||||
ag_get_next_completed_task (Display *display)
|
||||
{
|
||||
AgPerDisplayData *dd;
|
||||
|
||||
dd = get_display_data (display, False);
|
||||
|
||||
if (dd == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
printf ("%d pending %d completed\n",
|
||||
dd->n_tasks_pending,
|
||||
dd->n_tasks_completed);
|
||||
#endif
|
||||
|
||||
return (AgGetPropertyTask*) dd->completed_tasks;
|
||||
}
|
||||
|
||||
void*
|
||||
ag_Xmalloc (unsigned long bytes)
|
||||
{
|
||||
return (void*) Xmalloc (bytes);
|
||||
}
|
||||
|
||||
void*
|
||||
ag_Xmalloc0 (unsigned long bytes)
|
||||
{
|
||||
return (void*) Xcalloc (bytes, 1);
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Asynchronous X property getting hack */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of The Open Group shall not be
|
||||
* used in advertising or otherwise to promote the sale, use or other dealings
|
||||
* in this Software without prior written authorization from The Open Group.
|
||||
*/
|
||||
|
||||
#ifndef ASYNC_GETPROP_H
|
||||
#define ASYNC_GETPROP_H
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
typedef struct _AgGetPropertyTask AgGetPropertyTask;
|
||||
|
||||
AgGetPropertyTask* ag_task_create (Display *display,
|
||||
Window window,
|
||||
Atom property,
|
||||
long offset,
|
||||
long length,
|
||||
Bool delete,
|
||||
Atom req_type);
|
||||
Status ag_task_get_reply_and_free (AgGetPropertyTask *task,
|
||||
Atom *actual_type,
|
||||
int *actual_format,
|
||||
unsigned long *nitems,
|
||||
unsigned long *bytesafter,
|
||||
unsigned char **prop);
|
||||
|
||||
Bool ag_task_have_reply (AgGetPropertyTask *task);
|
||||
Atom ag_task_get_property (AgGetPropertyTask *task);
|
||||
Window ag_task_get_window (AgGetPropertyTask *task);
|
||||
Display* ag_task_get_display (AgGetPropertyTask *task);
|
||||
|
||||
AgGetPropertyTask* ag_get_next_completed_task (Display *display);
|
||||
|
||||
/* so other headers don't have to include internal Xlib goo */
|
||||
void* ag_Xmalloc (unsigned long bytes);
|
||||
void* ag_Xmalloc0 (unsigned long bytes);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-xwayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-xwayland-private.h"
|
||||
#endif
|
||||
|
||||
static XIEvent *
|
||||
@@ -1676,6 +1677,15 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor () &&
|
||||
meta_xwayland_selection_handle_event (event))
|
||||
{
|
||||
bypass_gtk = bypass_compositor = TRUE;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
|
@@ -50,6 +50,11 @@ meta_group_new (MetaDisplay *display,
|
||||
group->group_leader = group_leader;
|
||||
group->refcount = 1; /* owned by caller, hash table has only weak ref */
|
||||
|
||||
XWindowAttributes attrs;
|
||||
XGetWindowAttributes (display->xdisplay, group_leader, &attrs);
|
||||
XSelectInput (display->xdisplay, group_leader,
|
||||
attrs.your_event_mask | PropertyChangeMask);
|
||||
|
||||
if (display->groups_by_leader == NULL)
|
||||
display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash,
|
||||
meta_unsigned_long_equal);
|
||||
|
@@ -60,10 +60,10 @@ SOFTWARE.
|
||||
#ifndef _XATOMTYPE_H_
|
||||
#define _XATOMTYPE_H_
|
||||
|
||||
#define BOOL long
|
||||
#define SIGNEDINT long
|
||||
#define UNSIGNEDINT unsigned long
|
||||
#define RESOURCEID unsigned long
|
||||
#define BOOL int32_t
|
||||
#define SIGNEDINT int32_t
|
||||
#define UNSIGNEDINT uint32_t
|
||||
#define RESOURCEID uint32_t
|
||||
|
||||
|
||||
/* this structure may be extended, but do not change the order */
|
||||
|
@@ -1,496 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of The Open Group shall not be
|
||||
* used in advertising or otherwise to promote the sale, use or other dealings
|
||||
* in this Software without prior written authorization from The Open Group.
|
||||
*/
|
||||
|
||||
#include "async-getprop.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*) 0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
static void
|
||||
print_backtrace (void)
|
||||
{
|
||||
void *bt[500];
|
||||
int bt_size;
|
||||
int i;
|
||||
char **syms;
|
||||
|
||||
bt_size = backtrace (bt, 500);
|
||||
|
||||
syms = backtrace_symbols (bt, bt_size);
|
||||
|
||||
i = 0;
|
||||
while (i < bt_size)
|
||||
{
|
||||
fprintf (stderr, " %s\n", syms[i]);
|
||||
++i;
|
||||
}
|
||||
|
||||
free (syms);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
print_backtrace (void)
|
||||
{
|
||||
fprintf (stderr, "Not compiled with backtrace support\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static int error_trap_depth = 0;
|
||||
|
||||
static int
|
||||
x_error_handler (Display *xdisplay,
|
||||
XErrorEvent *error)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
||||
|
||||
if (error_trap_depth == 0)
|
||||
{
|
||||
print_backtrace ();
|
||||
|
||||
fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 1; /* return value is meaningless */
|
||||
}
|
||||
|
||||
static void
|
||||
error_trap_push (Display *xdisplay)
|
||||
{
|
||||
++error_trap_depth;
|
||||
}
|
||||
|
||||
static void
|
||||
error_trap_pop (Display *xdisplay)
|
||||
{
|
||||
if (error_trap_depth == 0)
|
||||
{
|
||||
fprintf (stderr, "Error trap underflow!\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
XSync (xdisplay, False); /* get all errors out of the queue */
|
||||
--error_trap_depth;
|
||||
}
|
||||
|
||||
static char*
|
||||
my_strdup (const char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = malloc (strlen (str) + 1);
|
||||
if (s == NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc failed\n");
|
||||
exit (1);
|
||||
}
|
||||
strcpy (s, str);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static char*
|
||||
atom_name (Display *display,
|
||||
Atom atom)
|
||||
{
|
||||
if (atom == None)
|
||||
{
|
||||
return my_strdup ("None");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *xname;
|
||||
char *ret;
|
||||
|
||||
error_trap_push (display);
|
||||
xname = XGetAtomName (display, atom);
|
||||
error_trap_pop (display);
|
||||
if (xname == NULL)
|
||||
return my_strdup ("[unknown atom]");
|
||||
|
||||
ret = my_strdup (xname);
|
||||
XFree (xname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ELAPSED(start_time, current_time) \
|
||||
(((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
|
||||
(current_time.tv_usec - start_time.tv_usec))) / 1000.0)
|
||||
|
||||
static struct timeval program_start_time;
|
||||
|
||||
static Bool
|
||||
try_get_reply (Display *xdisplay,
|
||||
AgGetPropertyTask *task)
|
||||
{
|
||||
if (ag_task_have_reply (task))
|
||||
{
|
||||
int result;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long n_items;
|
||||
unsigned long bytes_after;
|
||||
unsigned char *data;
|
||||
char *name;
|
||||
struct timeval current_time;
|
||||
|
||||
gettimeofday (¤t_time, NULL);
|
||||
|
||||
printf (" %gms (we have a reply for property %ld)\n",
|
||||
ELAPSED (program_start_time, current_time),
|
||||
ag_task_get_property (task));
|
||||
|
||||
data = NULL;
|
||||
|
||||
name = atom_name (xdisplay,
|
||||
ag_task_get_property (task));
|
||||
printf (" %s on 0x%lx:\n", name,
|
||||
ag_task_get_window (task));
|
||||
free (name);
|
||||
|
||||
result = ag_task_get_reply_and_free (task,
|
||||
&actual_type,
|
||||
&actual_format,
|
||||
&n_items,
|
||||
&bytes_after,
|
||||
&data);
|
||||
task = NULL;
|
||||
|
||||
if (result != Success)
|
||||
{
|
||||
fprintf (stderr, " error code %d getting reply\n", result);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = atom_name (xdisplay, actual_type);
|
||||
printf (" actual_type = %s\n", name);
|
||||
free (name);
|
||||
|
||||
printf (" actual_format = %d\n", actual_format);
|
||||
|
||||
printf (" n_items = %lu\n", n_items);
|
||||
printf (" bytes_after = %lu\n", bytes_after);
|
||||
|
||||
printf (" data = \"%s\"\n", data ? (char*) data : "NULL");
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static void run_speed_comparison (Display *xdisplay,
|
||||
Window window);
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
Display *xdisplay;
|
||||
int i;
|
||||
int n_left;
|
||||
int n_props;
|
||||
Window window;
|
||||
const char *window_str;
|
||||
char *end;
|
||||
Atom *props;
|
||||
struct timeval current_time;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf (stderr, "specify window ID\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
window_str = argv[1];
|
||||
|
||||
end = NULL;
|
||||
window = strtoul (window_str, &end, 0);
|
||||
if (end == NULL || *end != '\0')
|
||||
{
|
||||
fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
xdisplay = XOpenDisplay (NULL);
|
||||
if (xdisplay == NULL)
|
||||
{
|
||||
fprintf (stderr, "Could not open display\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getenv ("MUTTER_SYNC") != NULL)
|
||||
XSynchronize (xdisplay, True);
|
||||
|
||||
XSetErrorHandler (x_error_handler);
|
||||
|
||||
n_props = 0;
|
||||
props = XListProperties (xdisplay, window, &n_props);
|
||||
if (n_props == 0 || props == NULL)
|
||||
{
|
||||
fprintf (stderr, "Window has no properties\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
gettimeofday (&program_start_time, NULL);
|
||||
|
||||
i = 0;
|
||||
while (i < n_props)
|
||||
{
|
||||
gettimeofday (¤t_time, NULL);
|
||||
printf (" %gms (sending request for property %ld)\n",
|
||||
ELAPSED (program_start_time, current_time),
|
||||
props[i]);
|
||||
if (ag_task_create (xdisplay,
|
||||
window, props[i],
|
||||
0, 0xffffffff,
|
||||
False,
|
||||
AnyPropertyType) == NULL)
|
||||
{
|
||||
fprintf (stderr, "Failed to send request\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
XFree (props);
|
||||
props = NULL;
|
||||
|
||||
n_left = n_props;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
XEvent xevent;
|
||||
int connection;
|
||||
fd_set set;
|
||||
AgGetPropertyTask *task;
|
||||
|
||||
/* Mop up event queue */
|
||||
while (XPending (xdisplay) > 0)
|
||||
{
|
||||
XNextEvent (xdisplay, &xevent);
|
||||
gettimeofday (¤t_time, NULL);
|
||||
printf (" %gms (processing event type %d)\n",
|
||||
ELAPSED (program_start_time, current_time),
|
||||
xevent.xany.type);
|
||||
}
|
||||
|
||||
while ((task = ag_get_next_completed_task (xdisplay)))
|
||||
{
|
||||
try_get_reply (xdisplay, task);
|
||||
n_left -= 1;
|
||||
}
|
||||
|
||||
if (n_left == 0)
|
||||
{
|
||||
printf ("All %d replies received.\n", n_props);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wake up if we may have a reply */
|
||||
connection = ConnectionNumber (xdisplay);
|
||||
|
||||
FD_ZERO (&set);
|
||||
FD_SET (connection, &set);
|
||||
|
||||
gettimeofday (¤t_time, NULL);
|
||||
printf (" %gms (blocking for data %d left)\n",
|
||||
ELAPSED (program_start_time, current_time), n_left);
|
||||
select (connection + 1, &set, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
run_speed_comparison (xdisplay, window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function doesn't have all the printf's
|
||||
* and other noise, it just compares async to sync
|
||||
*/
|
||||
static void
|
||||
run_speed_comparison (Display *xdisplay,
|
||||
Window window)
|
||||
{
|
||||
int i;
|
||||
int n_props;
|
||||
struct timeval start, end;
|
||||
int n_left;
|
||||
|
||||
/* We just use atom values (0 to n_props) % 200, many are probably
|
||||
* BadAtom, that's fine, but the %200 keeps most of them valid. The
|
||||
* async case is about twice as advantageous when using valid atoms
|
||||
* (or the issue may be that it's more advantageous when the
|
||||
* properties are present and data is transmitted).
|
||||
*/
|
||||
n_props = 4000;
|
||||
printf ("Timing with %d property requests\n", n_props);
|
||||
|
||||
gettimeofday (&start, NULL);
|
||||
|
||||
i = 0;
|
||||
while (i < n_props)
|
||||
{
|
||||
if (ag_task_create (xdisplay,
|
||||
window, (Atom) i % 200,
|
||||
0, 0xffffffff,
|
||||
False,
|
||||
AnyPropertyType) == NULL)
|
||||
{
|
||||
fprintf (stderr, "Failed to send request\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
n_left = n_props;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
int connection;
|
||||
fd_set set;
|
||||
XEvent xevent;
|
||||
AgGetPropertyTask *task;
|
||||
|
||||
/* Mop up event queue */
|
||||
while (XPending (xdisplay) > 0)
|
||||
XNextEvent (xdisplay, &xevent);
|
||||
|
||||
while ((task = ag_get_next_completed_task (xdisplay)))
|
||||
{
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long n_items;
|
||||
unsigned long bytes_after;
|
||||
unsigned char *data;
|
||||
|
||||
assert (ag_task_have_reply (task));
|
||||
|
||||
data = NULL;
|
||||
ag_task_get_reply_and_free (task,
|
||||
&actual_type,
|
||||
&actual_format,
|
||||
&n_items,
|
||||
&bytes_after,
|
||||
&data);
|
||||
|
||||
if (data)
|
||||
XFree (data);
|
||||
|
||||
n_left -= 1;
|
||||
}
|
||||
|
||||
if (n_left == 0)
|
||||
break;
|
||||
|
||||
/* Wake up if we may have a reply */
|
||||
connection = ConnectionNumber (xdisplay);
|
||||
|
||||
FD_ZERO (&set);
|
||||
FD_SET (connection, &set);
|
||||
|
||||
select (connection + 1, &set, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
gettimeofday (&end, NULL);
|
||||
|
||||
printf ("Async time: %gms\n",
|
||||
ELAPSED (start, end));
|
||||
|
||||
gettimeofday (&start, NULL);
|
||||
|
||||
error_trap_push (xdisplay);
|
||||
|
||||
i = 0;
|
||||
while (i < n_props)
|
||||
{
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long n_items;
|
||||
unsigned long bytes_after;
|
||||
unsigned char *data;
|
||||
|
||||
data = NULL;
|
||||
if (XGetWindowProperty (xdisplay, window,
|
||||
(Atom) i % 200,
|
||||
0, 0xffffffff,
|
||||
False,
|
||||
AnyPropertyType,
|
||||
&actual_type,
|
||||
&actual_format,
|
||||
&n_items,
|
||||
&bytes_after,
|
||||
&data) == Success)
|
||||
{
|
||||
if (data)
|
||||
XFree (data);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
error_trap_pop (xdisplay);
|
||||
|
||||
gettimeofday (&end, NULL);
|
||||
|
||||
printf ("Sync time: %gms\n",
|
||||
ELAPSED (start, end));
|
||||
}
|
@@ -428,10 +428,10 @@ reload_net_wm_pid (MetaWindow *window,
|
||||
{
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
gulong cardinal = (int) value->v.cardinal;
|
||||
uint32_t cardinal = (int) value->v.cardinal;
|
||||
|
||||
if (cardinal <= 0)
|
||||
meta_warning ("Application set a bogus _NET_WM_PID %lu\n",
|
||||
meta_warning ("Application set a bogus _NET_WM_PID %u\n",
|
||||
cardinal);
|
||||
else
|
||||
{
|
||||
@@ -449,7 +449,7 @@ reload_net_wm_user_time (MetaWindow *window,
|
||||
{
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
gulong cardinal = value->v.cardinal;
|
||||
uint32_t cardinal = value->v.cardinal;
|
||||
meta_window_set_user_time (window, cardinal);
|
||||
}
|
||||
}
|
||||
@@ -670,7 +670,7 @@ reload_opaque_region (MetaWindow *window,
|
||||
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
gulong *region = value->v.cardinal_list.cardinals;
|
||||
uint32_t *region = value->v.cardinal_list.cardinals;
|
||||
int nitems = value->v.cardinal_list.n_cardinals;
|
||||
|
||||
cairo_rectangle_int_t *rects;
|
||||
@@ -862,7 +862,7 @@ reload_mwm_hints (MetaWindow *window,
|
||||
|
||||
if (hints->flags & MWM_HINTS_DECORATIONS)
|
||||
{
|
||||
meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%lx\n",
|
||||
meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%x\n",
|
||||
window->desc, hints->decorations);
|
||||
|
||||
if (hints->decorations == 0)
|
||||
@@ -878,7 +878,7 @@ reload_mwm_hints (MetaWindow *window,
|
||||
{
|
||||
gboolean toggle_value;
|
||||
|
||||
meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%lx\n",
|
||||
meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%x\n",
|
||||
window->desc, hints->functions);
|
||||
|
||||
/* If _ALL is specified, then other flags indicate what to turn off;
|
||||
|
@@ -1283,7 +1283,7 @@ meta_window_x11_update_struts (MetaWindow *window)
|
||||
GSList *old_struts;
|
||||
GSList *new_struts;
|
||||
GSList *old_iter, *new_iter;
|
||||
gulong *struts = NULL;
|
||||
uint32_t *struts = NULL;
|
||||
int nitems;
|
||||
gboolean changed;
|
||||
|
||||
@@ -1346,7 +1346,7 @@ meta_window_x11_update_struts (MetaWindow *window)
|
||||
new_struts = g_slist_prepend (new_struts, temp);
|
||||
}
|
||||
|
||||
meta_verbose ("_NET_WM_STRUT_PARTIAL struts %lu %lu %lu %lu for "
|
||||
meta_verbose ("_NET_WM_STRUT_PARTIAL struts %u %u %u %u for "
|
||||
"window %s\n",
|
||||
struts[0], struts[1], struts[2], struts[3],
|
||||
window->desc);
|
||||
@@ -1405,7 +1405,7 @@ meta_window_x11_update_struts (MetaWindow *window)
|
||||
new_struts = g_slist_prepend (new_struts, temp);
|
||||
}
|
||||
|
||||
meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n",
|
||||
meta_verbose ("_NET_WM_STRUT struts %u %u %u %u for window %s\n",
|
||||
struts[0], struts[1], struts[2], struts[3],
|
||||
window->desc);
|
||||
}
|
||||
@@ -2774,7 +2774,7 @@ maybe_filter_xwindow (MetaDisplay *display,
|
||||
*/
|
||||
if (!must_be_viewable || attrs->map_state == IsViewable)
|
||||
{
|
||||
gulong old_state;
|
||||
uint32_t old_state;
|
||||
|
||||
if (!meta_prop_get_cardinal_with_atom_type (display, xwindow,
|
||||
display->atom_WM_STATE,
|
||||
@@ -2910,7 +2910,7 @@ meta_window_x11_new (MetaDisplay *display,
|
||||
if (must_be_viewable && attrs.map_state != IsViewable)
|
||||
{
|
||||
/* Only manage if WM_STATE is IconicState or NormalState */
|
||||
gulong state;
|
||||
uint32_t state;
|
||||
|
||||
/* WM_STATE isn't a cardinal, it's type WM_STATE, but is an int */
|
||||
if (!(meta_prop_get_cardinal_with_atom_type (display, xwindow,
|
||||
|
507
src/x11/xprops.c
507
src/x11/xprops.c
@@ -78,17 +78,21 @@ from The Open Group.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xprops.h"
|
||||
#include <meta/errors.h>
|
||||
#include "util-private.h"
|
||||
#include "async-getprop.h"
|
||||
#include "ui.h"
|
||||
#include "mutter-Xatomtype.h"
|
||||
#include <X11/Xatom.h>
|
||||
#include <string.h>
|
||||
#include "window-private.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaDisplay *display;
|
||||
@@ -168,13 +172,50 @@ validate_or_free_results (GetPropertyResults *results,
|
||||
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static xcb_get_property_cookie_t
|
||||
async_get_property (xcb_connection_t *xcb_conn, Window xwindow,
|
||||
Atom xatom, Atom required_type)
|
||||
{
|
||||
return xcb_get_property (xcb_conn, False, xwindow,
|
||||
xatom, required_type, 0, G_MAXUINT32);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
async_get_property_finish (xcb_connection_t *xcb_conn,
|
||||
xcb_get_property_cookie_t cookie,
|
||||
GetPropertyResults *results)
|
||||
{
|
||||
xcb_get_property_reply_t *reply;
|
||||
xcb_generic_error_t *error;
|
||||
|
||||
reply = xcb_get_property_reply (xcb_conn, cookie, &error);
|
||||
if (error)
|
||||
{
|
||||
free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
results->n_items = reply->value_len;
|
||||
results->type = reply->type;
|
||||
results->bytes_after = reply->bytes_after;
|
||||
results->format = reply->format;
|
||||
results->prop = NULL;
|
||||
|
||||
if (results->type != None)
|
||||
results->prop = g_memdup (xcb_get_property_value (reply),
|
||||
xcb_get_property_value_length (reply));
|
||||
|
||||
free (reply);
|
||||
return (results->prop != NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_property (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
@@ -182,6 +223,9 @@ get_property (MetaDisplay *display,
|
||||
Atom req_type,
|
||||
GetPropertyResults *results)
|
||||
{
|
||||
xcb_get_property_cookie_t cookie;
|
||||
xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
|
||||
|
||||
results->display = display;
|
||||
results->xwindow = xwindow;
|
||||
results->xatom = xatom;
|
||||
@@ -191,87 +235,37 @@ get_property (MetaDisplay *display,
|
||||
results->bytes_after = 0;
|
||||
results->format = 0;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
|
||||
0, G_MAXLONG,
|
||||
False, req_type, &results->type, &results->format,
|
||||
&results->n_items,
|
||||
&results->bytes_after,
|
||||
&results->prop) != Success ||
|
||||
results->type == None)
|
||||
{
|
||||
if (results->prop)
|
||||
XFree (results->prop);
|
||||
meta_error_trap_pop_with_return (display);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
if (results->prop)
|
||||
XFree (results->prop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
cookie = async_get_property (xcb_conn, xwindow, xatom, req_type);
|
||||
return async_get_property_finish (xcb_conn, cookie, results);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
atom_list_from_results (GetPropertyResults *results,
|
||||
Atom **atoms_p,
|
||||
uint32_t **atoms_p,
|
||||
int *n_atoms_p)
|
||||
{
|
||||
if (!validate_or_free_results (results, 32, XA_ATOM, FALSE))
|
||||
return FALSE;
|
||||
|
||||
*atoms_p = (Atom*) results->prop;
|
||||
*atoms_p = (uint32_t*) results->prop;
|
||||
*n_atoms_p = results->n_items;
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_atom_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
Atom **atoms_p,
|
||||
int *n_atoms_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
*atoms_p = NULL;
|
||||
*n_atoms_p = 0;
|
||||
|
||||
if (!get_property (display, xwindow, xatom, XA_ATOM,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return atom_list_from_results (&results, atoms_p, n_atoms_p);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cardinal_list_from_results (GetPropertyResults *results,
|
||||
gulong **cardinals_p,
|
||||
uint32_t **cardinals_p,
|
||||
int *n_cardinals_p)
|
||||
{
|
||||
if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE))
|
||||
return FALSE;
|
||||
|
||||
*cardinals_p = (gulong*) results->prop;
|
||||
*cardinals_p = (uint32_t *) results->prop;
|
||||
*n_cardinals_p = results->n_items;
|
||||
results->prop = NULL;
|
||||
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < *n_cardinals_p; i++)
|
||||
(*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -279,7 +273,7 @@ gboolean
|
||||
meta_prop_get_cardinal_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
gulong **cardinals_p,
|
||||
uint32_t **cardinals_p,
|
||||
int *n_cardinals_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
@@ -298,19 +292,11 @@ static gboolean
|
||||
motif_hints_from_results (GetPropertyResults *results,
|
||||
MotifWmHints **hints_p)
|
||||
{
|
||||
int real_size, max_size;
|
||||
#define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong)
|
||||
|
||||
*hints_p = NULL;
|
||||
|
||||
if (results->type == None || results->n_items <= 0)
|
||||
{
|
||||
meta_verbose ("Motif hints had unexpected type or n_items\n");
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -318,26 +304,12 @@ motif_hints_from_results (GetPropertyResults *results,
|
||||
* MotifWmHints than the one we expect, apparently. I'm not sure of
|
||||
* the history behind it. See bug #89841 for example.
|
||||
*/
|
||||
*hints_p = ag_Xmalloc (sizeof (MotifWmHints));
|
||||
*hints_p = calloc (1, sizeof (MotifWmHints));
|
||||
if (*hints_p == NULL)
|
||||
{
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
real_size = results->n_items * sizeof (gulong);
|
||||
max_size = MAX_ITEMS * sizeof (gulong);
|
||||
memcpy (*hints_p, results->prop, MIN (real_size, max_size));
|
||||
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
memcpy(*hints_p, results->prop, MIN (sizeof (MotifWmHints),
|
||||
results->n_items * sizeof (uint32_t)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -367,8 +339,7 @@ latin1_string_from_results (GetPropertyResults *results,
|
||||
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
|
||||
return FALSE;
|
||||
|
||||
*str_p = (char*) results->prop;
|
||||
results->prop = NULL;
|
||||
*str_p = g_strndup ((char *) results->prop, results->n_items);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -409,36 +380,17 @@ utf8_string_from_results (GetPropertyResults *results,
|
||||
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8\n",
|
||||
name, results->xwindow);
|
||||
meta_XFree (name);
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*str_p = (char*) results->prop;
|
||||
results->prop = NULL;
|
||||
*str_p = g_strndup ((char *) results->prop, results->n_items);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_utf8_string (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char **str_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
*str_p = NULL;
|
||||
|
||||
if (!get_property (display, xwindow, xatom,
|
||||
display->atom_UTF8_STRING,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return utf8_string_from_results (&results, str_p);
|
||||
}
|
||||
|
||||
/* this one freakishly returns g_malloc memory */
|
||||
static gboolean
|
||||
utf8_list_from_results (GetPropertyResults *results,
|
||||
@@ -492,7 +444,7 @@ utf8_list_from_results (GetPropertyResults *results,
|
||||
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n",
|
||||
name, results->xwindow, i);
|
||||
meta_XFree (name);
|
||||
meta_XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
g_strfreev (retval);
|
||||
@@ -508,7 +460,7 @@ utf8_list_from_results (GetPropertyResults *results,
|
||||
*str_p = retval;
|
||||
*n_str_p = i;
|
||||
|
||||
meta_XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
@@ -534,81 +486,6 @@ meta_prop_get_utf8_list (MetaDisplay *display,
|
||||
return utf8_list_from_results (&results, str_p, n_str_p);
|
||||
}
|
||||
|
||||
/* this one freakishly returns g_malloc memory */
|
||||
static gboolean
|
||||
latin1_list_from_results (GetPropertyResults *results,
|
||||
char ***str_p,
|
||||
int *n_str_p)
|
||||
{
|
||||
int i;
|
||||
int n_strings;
|
||||
char **retval;
|
||||
const char *p;
|
||||
|
||||
*str_p = NULL;
|
||||
*n_str_p = 0;
|
||||
|
||||
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
|
||||
return FALSE;
|
||||
|
||||
/* I'm not sure this is right, but I'm guessing the
|
||||
* property is nul-separated
|
||||
*/
|
||||
i = 0;
|
||||
n_strings = 0;
|
||||
while (i < (int) results->n_items)
|
||||
{
|
||||
if (results->prop[i] == '\0')
|
||||
++n_strings;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (results->prop[results->n_items - 1] != '\0')
|
||||
++n_strings;
|
||||
|
||||
/* we're guaranteed that results->prop has a nul on the end
|
||||
* by XGetWindowProperty
|
||||
*/
|
||||
|
||||
retval = g_new0 (char*, n_strings + 1);
|
||||
|
||||
p = (char *)results->prop;
|
||||
i = 0;
|
||||
while (i < n_strings)
|
||||
{
|
||||
retval[i] = g_strdup (p);
|
||||
|
||||
p = p + strlen (p) + 1;
|
||||
++i;
|
||||
}
|
||||
|
||||
*str_p = retval;
|
||||
*n_str_p = i;
|
||||
|
||||
meta_XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_latin1_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char ***str_p,
|
||||
int *n_str_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
*str_p = NULL;
|
||||
|
||||
if (!get_property (display, xwindow, xatom,
|
||||
XA_STRING, &results))
|
||||
return FALSE;
|
||||
|
||||
return latin1_list_from_results (&results, str_p, n_str_p);
|
||||
}
|
||||
|
||||
void
|
||||
meta_prop_set_utf8_string_hint (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
@@ -631,7 +508,7 @@ window_from_results (GetPropertyResults *results,
|
||||
return FALSE;
|
||||
|
||||
*window_p = *(Window*) results->prop;
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
@@ -647,7 +524,7 @@ counter_from_results (GetPropertyResults *results,
|
||||
return FALSE;
|
||||
|
||||
*counter_p = *(XSyncCounter*) results->prop;
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
@@ -655,7 +532,7 @@ counter_from_results (GetPropertyResults *results,
|
||||
|
||||
static gboolean
|
||||
counter_list_from_results (GetPropertyResults *results,
|
||||
XSyncCounter **counters_p,
|
||||
uint32_t **counters_p,
|
||||
int *n_counters_p)
|
||||
{
|
||||
if (!validate_or_free_results (results, 32,
|
||||
@@ -663,7 +540,7 @@ counter_list_from_results (GetPropertyResults *results,
|
||||
FALSE))
|
||||
return FALSE;
|
||||
|
||||
*counters_p = (XSyncCounter*) results->prop;
|
||||
*counters_p = (uint32_t *) results->prop;
|
||||
*n_counters_p = results->n_items;
|
||||
results->prop = NULL;
|
||||
|
||||
@@ -691,7 +568,7 @@ gboolean
|
||||
meta_prop_get_cardinal (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
gulong *cardinal_p)
|
||||
uint32_t *cardinal_p)
|
||||
{
|
||||
return meta_prop_get_cardinal_with_atom_type (display, xwindow, xatom,
|
||||
XA_CARDINAL, cardinal_p);
|
||||
@@ -700,17 +577,13 @@ meta_prop_get_cardinal (MetaDisplay *display,
|
||||
static gboolean
|
||||
cardinal_with_atom_type_from_results (GetPropertyResults *results,
|
||||
Atom prop_type,
|
||||
gulong *cardinal_p)
|
||||
uint32_t *cardinal_p)
|
||||
{
|
||||
if (!validate_or_free_results (results, 32, prop_type, TRUE))
|
||||
return FALSE;
|
||||
|
||||
*cardinal_p = *(gulong*) results->prop;
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
*cardinal_p &= 0xffffffff;
|
||||
#endif
|
||||
XFree (results->prop);
|
||||
*cardinal_p = *((uint32_t *) results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
@@ -721,7 +594,7 @@ meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
Atom prop_type,
|
||||
gulong *cardinal_p)
|
||||
uint32_t *cardinal_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
@@ -779,46 +652,6 @@ text_property_from_results (GetPropertyResults *results,
|
||||
return *utf8_str_p != NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_text_property (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char **utf8_str_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
if (!get_property (display, xwindow, xatom, AnyPropertyType,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return text_property_from_results (&results, utf8_str_p);
|
||||
}
|
||||
|
||||
/* From Xmd.h */
|
||||
#ifndef cvtINT32toInt
|
||||
#if SIZEOF_VOID_P == 8
|
||||
#define cvtINT8toInt(val) ((((unsigned int)val) & 0x00000080) ? (((unsigned int)val) | 0xffffffffffffff00) : ((unsigned int)val))
|
||||
#define cvtINT16toInt(val) ((((unsigned int)val) & 0x00008000) ? (((unsigned int)val) | 0xffffffffffff0000) : ((unsigned int)val))
|
||||
#define cvtINT32toInt(val) ((((unsigned int)val) & 0x80000000) ? (((unsigned int)val) | 0xffffffff00000000) : ((unsigned int)val))
|
||||
#define cvtINT8toShort(val) cvtINT8toInt(val)
|
||||
#define cvtINT16toShort(val) cvtINT16toInt(val)
|
||||
#define cvtINT32toShort(val) cvtINT32toInt(val)
|
||||
#define cvtINT8toLong(val) cvtINT8toInt(val)
|
||||
#define cvtINT16toLong(val) cvtINT16toInt(val)
|
||||
#define cvtINT32toLong(val) cvtINT32toInt(val)
|
||||
#else
|
||||
#define cvtINT8toInt(val) (val)
|
||||
#define cvtINT16toInt(val) (val)
|
||||
#define cvtINT32toInt(val) (val)
|
||||
#define cvtINT8toShort(val) (val)
|
||||
#define cvtINT16toShort(val) (val)
|
||||
#define cvtINT32toShort(val) (val)
|
||||
#define cvtINT8toLong(val) (val)
|
||||
#define cvtINT16toLong(val) (val)
|
||||
#define cvtINT32toLong(val) (val)
|
||||
#endif /* SIZEOF_VOID_P == 8 */
|
||||
#endif /* cvtINT32toInt() */
|
||||
|
||||
static gboolean
|
||||
wm_hints_from_results (GetPropertyResults *results,
|
||||
XWMHints **hints_p)
|
||||
@@ -838,23 +671,23 @@ wm_hints_from_results (GetPropertyResults *results,
|
||||
(int) results->n_items, NumPropWMHintsElements - 1);
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hints = ag_Xmalloc0 (sizeof (XWMHints));
|
||||
hints = calloc (1, sizeof (XWMHints));
|
||||
|
||||
raw = (xPropWMHints*) results->prop;
|
||||
|
||||
hints->flags = raw->flags;
|
||||
hints->input = (raw->input ? True : False);
|
||||
hints->initial_state = cvtINT32toInt (raw->initialState);
|
||||
hints->initial_state = raw->initialState;
|
||||
hints->icon_pixmap = raw->iconPixmap;
|
||||
hints->icon_window = raw->iconWindow;
|
||||
hints->icon_x = cvtINT32toInt (raw->iconX);
|
||||
hints->icon_y = cvtINT32toInt (raw->iconY);
|
||||
hints->icon_x = raw->iconX;
|
||||
hints->icon_y = raw->iconY;
|
||||
hints->icon_mask = raw->iconMask;
|
||||
if (results->n_items >= NumPropWMHintsElements)
|
||||
hints->window_group = raw->windowGroup;
|
||||
@@ -863,7 +696,7 @@ wm_hints_from_results (GetPropertyResults *results,
|
||||
|
||||
if (results->prop)
|
||||
{
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
}
|
||||
|
||||
@@ -872,23 +705,6 @@ wm_hints_from_results (GetPropertyResults *results,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_wm_hints (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XWMHints **hints_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
*hints_p = NULL;
|
||||
|
||||
if (!get_property (display, xwindow, xatom, XA_WM_HINTS,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return wm_hints_from_results (&results, hints_p);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
class_hint_from_results (GetPropertyResults *results,
|
||||
XClassHint *class_hint)
|
||||
@@ -902,9 +718,9 @@ class_hint_from_results (GetPropertyResults *results,
|
||||
return FALSE;
|
||||
|
||||
len_name = strlen ((char *) results->prop);
|
||||
if (! (class_hint->res_name = ag_Xmalloc (len_name+1)))
|
||||
if (! (class_hint->res_name = malloc (len_name+1)))
|
||||
{
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -916,41 +732,23 @@ class_hint_from_results (GetPropertyResults *results,
|
||||
|
||||
len_class = strlen ((char *)results->prop + len_name + 1);
|
||||
|
||||
if (! (class_hint->res_class = ag_Xmalloc(len_class+1)))
|
||||
if (! (class_hint->res_class = malloc(len_class+1)))
|
||||
{
|
||||
XFree(class_hint->res_name);
|
||||
class_hint->res_name = NULL;
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strcpy (class_hint->res_class, (char *)results->prop + len_name + 1);
|
||||
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_class_hint (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XClassHint *class_hint)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
class_hint->res_class = NULL;
|
||||
class_hint->res_name = NULL;
|
||||
|
||||
if (!get_property (display, xwindow, xatom, XA_STRING,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return class_hint_from_results (&results, class_hint);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
size_hints_from_results (GetPropertyResults *results,
|
||||
XSizeHints **hints_p,
|
||||
@@ -970,37 +768,36 @@ size_hints_from_results (GetPropertyResults *results,
|
||||
|
||||
raw = (xPropSizeHints*) results->prop;
|
||||
|
||||
hints = ag_Xmalloc (sizeof (XSizeHints));
|
||||
hints = malloc (sizeof (XSizeHints));
|
||||
|
||||
/* XSizeHints misdeclares these as int instead of long */
|
||||
hints->flags = raw->flags;
|
||||
hints->x = cvtINT32toInt (raw->x);
|
||||
hints->y = cvtINT32toInt (raw->y);
|
||||
hints->width = cvtINT32toInt (raw->width);
|
||||
hints->height = cvtINT32toInt (raw->height);
|
||||
hints->min_width = cvtINT32toInt (raw->minWidth);
|
||||
hints->min_height = cvtINT32toInt (raw->minHeight);
|
||||
hints->max_width = cvtINT32toInt (raw->maxWidth);
|
||||
hints->max_height = cvtINT32toInt (raw->maxHeight);
|
||||
hints->width_inc = cvtINT32toInt (raw->widthInc);
|
||||
hints->height_inc = cvtINT32toInt (raw->heightInc);
|
||||
hints->min_aspect.x = cvtINT32toInt (raw->minAspectX);
|
||||
hints->min_aspect.y = cvtINT32toInt (raw->minAspectY);
|
||||
hints->max_aspect.x = cvtINT32toInt (raw->maxAspectX);
|
||||
hints->max_aspect.y = cvtINT32toInt (raw->maxAspectY);
|
||||
hints->x = raw->x;
|
||||
hints->y = raw->y;
|
||||
hints->width = raw->width;
|
||||
hints->height = raw->height;
|
||||
hints->min_width = raw->minWidth;
|
||||
hints->min_height = raw->minHeight;
|
||||
hints->max_width = raw->maxWidth;
|
||||
hints->max_height = raw->maxHeight;
|
||||
hints->width_inc = raw->widthInc;
|
||||
hints->height_inc = raw->heightInc;
|
||||
hints->min_aspect.x = raw->minAspectX;
|
||||
hints->min_aspect.y = raw->minAspectY;
|
||||
hints->max_aspect.x = raw->maxAspectX;
|
||||
hints->max_aspect.y = raw->maxAspectY;
|
||||
|
||||
*flags_p = (USPosition | USSize | PAllHints);
|
||||
if (results->n_items >= NumPropSizeElements)
|
||||
{
|
||||
hints->base_width= cvtINT32toInt (raw->baseWidth);
|
||||
hints->base_height= cvtINT32toInt (raw->baseHeight);
|
||||
hints->win_gravity= cvtINT32toInt (raw->winGravity);
|
||||
hints->base_width = raw->baseWidth;
|
||||
hints->base_height = raw->baseHeight;
|
||||
hints->win_gravity = raw->winGravity;
|
||||
*flags_p |= (PBaseSize | PWinGravity);
|
||||
}
|
||||
|
||||
hints->flags &= (*flags_p); /* get rid of unwanted bits */
|
||||
|
||||
XFree (results->prop);
|
||||
g_free (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
*hints_p = hints;
|
||||
@@ -1008,37 +805,6 @@ size_hints_from_results (GetPropertyResults *results,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prop_get_size_hints (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XSizeHints **hints_p,
|
||||
gulong *flags_p)
|
||||
{
|
||||
GetPropertyResults results;
|
||||
|
||||
*hints_p = NULL;
|
||||
*flags_p = 0;
|
||||
|
||||
if (!get_property (display, xwindow, xatom, XA_WM_SIZE_HINTS,
|
||||
&results))
|
||||
return FALSE;
|
||||
|
||||
return size_hints_from_results (&results, hints_p, flags_p);
|
||||
}
|
||||
|
||||
static AgGetPropertyTask*
|
||||
get_task (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
Atom req_type)
|
||||
{
|
||||
return ag_task_create (display->xdisplay,
|
||||
xwindow,
|
||||
xatom, 0, G_MAXLONG,
|
||||
False, req_type);
|
||||
}
|
||||
|
||||
static char*
|
||||
latin1_to_utf8 (const char *text)
|
||||
{
|
||||
@@ -1064,7 +830,8 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
int n_values)
|
||||
{
|
||||
int i;
|
||||
AgGetPropertyTask **tasks;
|
||||
xcb_get_property_cookie_t *tasks;
|
||||
xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
|
||||
|
||||
meta_verbose ("Requesting %d properties of 0x%lx at once\n",
|
||||
n_values, xwindow);
|
||||
@@ -1072,7 +839,7 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
if (n_values == 0)
|
||||
return;
|
||||
|
||||
tasks = g_new0 (AgGetPropertyTask*, n_values);
|
||||
tasks = g_new0 (xcb_get_property_cookie_t, n_values);
|
||||
|
||||
/* Start up tasks. The "values" array can have values
|
||||
* with atom == None, which means to ignore that element.
|
||||
@@ -1132,9 +899,7 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
}
|
||||
|
||||
if (values[i].atom != None)
|
||||
tasks[i] = get_task (display, xwindow,
|
||||
values[i].atom, values[i].required_type);
|
||||
|
||||
tasks[i] = async_get_property (xcb_conn, xwindow, values[i].atom, values[i].required_type);
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -1147,10 +912,11 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
i = 0;
|
||||
while (i < n_values)
|
||||
{
|
||||
AgGetPropertyTask *task;
|
||||
GetPropertyResults results;
|
||||
|
||||
if (tasks[i] == NULL)
|
||||
/* We're relying on the fact that sequence numbers can never be zero
|
||||
* in Xorg. This is a bit disgusting... */
|
||||
if (tasks[i].sequence == 0)
|
||||
{
|
||||
/* Probably values[i].type was None, or ag_task_create()
|
||||
* returned NULL.
|
||||
@@ -1159,10 +925,6 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
goto next;
|
||||
}
|
||||
|
||||
task = ag_get_next_completed_task (display->xdisplay);
|
||||
g_assert (task != NULL);
|
||||
g_assert (ag_task_have_reply (task));
|
||||
|
||||
results.display = display;
|
||||
results.xwindow = xwindow;
|
||||
results.xatom = values[i].atom;
|
||||
@@ -1172,19 +934,9 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
results.bytes_after = 0;
|
||||
results.format = 0;
|
||||
|
||||
if (ag_task_get_reply_and_free (task,
|
||||
&results.type, &results.format,
|
||||
&results.n_items,
|
||||
&results.bytes_after,
|
||||
&results.prop) != Success ||
|
||||
results.type == None)
|
||||
if (!async_get_property_finish (xcb_conn, tasks[i], &results))
|
||||
{
|
||||
values[i].type = META_PROP_VALUE_INVALID;
|
||||
if (results.prop)
|
||||
{
|
||||
XFree (results.prop);
|
||||
results.prop = NULL;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
@@ -1216,18 +968,9 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
else
|
||||
{
|
||||
char *new_str;
|
||||
char *xmalloc_new_str;
|
||||
|
||||
new_str = latin1_to_utf8 (values[i].v.str);
|
||||
xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1);
|
||||
if (xmalloc_new_str != NULL)
|
||||
{
|
||||
strcpy (xmalloc_new_str, new_str);
|
||||
meta_XFree (values[i].v.str);
|
||||
values[i].v.str = xmalloc_new_str;
|
||||
}
|
||||
|
||||
g_free (new_str);
|
||||
free (values[i].v.str);
|
||||
values[i].v.str = new_str;
|
||||
}
|
||||
break;
|
||||
case META_PROP_VALUE_MOTIF_HINTS:
|
||||
@@ -1305,42 +1048,44 @@ free_value (MetaPropValue *value)
|
||||
break;
|
||||
case META_PROP_VALUE_UTF8:
|
||||
case META_PROP_VALUE_STRING:
|
||||
free (value->v.str);
|
||||
break;
|
||||
case META_PROP_VALUE_STRING_AS_UTF8:
|
||||
meta_XFree (value->v.str);
|
||||
g_free (value->v.str);
|
||||
break;
|
||||
case META_PROP_VALUE_MOTIF_HINTS:
|
||||
meta_XFree (value->v.motif_hints);
|
||||
free (value->v.motif_hints);
|
||||
break;
|
||||
case META_PROP_VALUE_CARDINAL:
|
||||
break;
|
||||
case META_PROP_VALUE_WINDOW:
|
||||
break;
|
||||
case META_PROP_VALUE_ATOM_LIST:
|
||||
meta_XFree (value->v.atom_list.atoms);
|
||||
free (value->v.atom_list.atoms);
|
||||
break;
|
||||
case META_PROP_VALUE_TEXT_PROPERTY:
|
||||
meta_XFree (value->v.str);
|
||||
free (value->v.str);
|
||||
break;
|
||||
case META_PROP_VALUE_WM_HINTS:
|
||||
meta_XFree (value->v.wm_hints);
|
||||
free (value->v.wm_hints);
|
||||
break;
|
||||
case META_PROP_VALUE_CLASS_HINT:
|
||||
meta_XFree (value->v.class_hint.res_class);
|
||||
meta_XFree (value->v.class_hint.res_name);
|
||||
free (value->v.class_hint.res_class);
|
||||
free (value->v.class_hint.res_name);
|
||||
break;
|
||||
case META_PROP_VALUE_SIZE_HINTS:
|
||||
meta_XFree (value->v.size_hints.hints);
|
||||
free (value->v.size_hints.hints);
|
||||
break;
|
||||
case META_PROP_VALUE_UTF8_LIST:
|
||||
g_strfreev (value->v.string_list.strings);
|
||||
break;
|
||||
case META_PROP_VALUE_CARDINAL_LIST:
|
||||
meta_XFree (value->v.cardinal_list.cardinals);
|
||||
free (value->v.cardinal_list.cardinals);
|
||||
break;
|
||||
case META_PROP_VALUE_SYNC_COUNTER:
|
||||
break;
|
||||
case META_PROP_VALUE_SYNC_COUNTER_LIST:
|
||||
meta_XFree (value->v.xcounter_list.counters);
|
||||
free (value->v.xcounter_list.counters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -33,11 +33,11 @@
|
||||
* found in some Motif reference guides online.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned long flags;
|
||||
unsigned long functions;
|
||||
unsigned long decorations;
|
||||
long input_mode;
|
||||
unsigned long status;
|
||||
uint32_t flags;
|
||||
uint32_t functions;
|
||||
uint32_t decorations;
|
||||
uint32_t input_mode;
|
||||
uint32_t status;
|
||||
} MotifWmHints, MwmHints;
|
||||
|
||||
#define MWM_HINTS_FUNCTIONS (1L << 0)
|
||||
@@ -71,11 +71,6 @@ typedef struct {
|
||||
/* These all return the memory from Xlib, so require an XFree()
|
||||
* when they return TRUE. They return TRUE on success.
|
||||
*/
|
||||
gboolean meta_prop_get_atom_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
Atom **atoms_p,
|
||||
int *n_atoms_p);
|
||||
gboolean meta_prop_get_motif_hints (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
@@ -83,26 +78,17 @@ gboolean meta_prop_get_motif_hints (MetaDisplay *display,
|
||||
gboolean meta_prop_get_cardinal_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
gulong **cardinals_p,
|
||||
uint32_t **cardinals_p,
|
||||
int *n_cardinals_p);
|
||||
gboolean meta_prop_get_latin1_string (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char **str_p);
|
||||
gboolean meta_prop_get_utf8_string (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char **str_p);
|
||||
gboolean meta_prop_get_utf8_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char ***str_p,
|
||||
int *n_str_p);
|
||||
gboolean meta_prop_get_latin1_list (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char ***str_p,
|
||||
int *n_str_p);
|
||||
void meta_prop_set_utf8_string_hint
|
||||
(MetaDisplay *display,
|
||||
Window xwindow,
|
||||
@@ -115,32 +101,12 @@ gboolean meta_prop_get_window (MetaDisplay *display,
|
||||
gboolean meta_prop_get_cardinal (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
gulong *cardinal_p);
|
||||
uint32_t *cardinal_p);
|
||||
gboolean meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
Atom prop_type,
|
||||
gulong *cardinal_p);
|
||||
gboolean meta_prop_get_text_property (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
char **utf8_str_p);
|
||||
|
||||
gboolean meta_prop_get_wm_hints (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XWMHints **hints_p);
|
||||
|
||||
gboolean meta_prop_get_class_hint (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XClassHint *class_hint);
|
||||
|
||||
gboolean meta_prop_get_size_hints (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom xatom,
|
||||
XSizeHints **hints_p,
|
||||
gulong *flags_p);
|
||||
uint32_t *cardinal_p);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -174,14 +140,14 @@ typedef struct
|
||||
char *str;
|
||||
MotifWmHints *motif_hints;
|
||||
Window xwindow;
|
||||
gulong cardinal;
|
||||
uint32_t cardinal;
|
||||
XWMHints *wm_hints;
|
||||
XClassHint class_hint;
|
||||
XSyncCounter xcounter;
|
||||
struct
|
||||
{
|
||||
gulong *counters;
|
||||
int n_counters;
|
||||
uint32_t *counters;
|
||||
int n_counters;
|
||||
} xcounter_list;
|
||||
|
||||
struct
|
||||
@@ -192,8 +158,8 @@ typedef struct
|
||||
|
||||
struct
|
||||
{
|
||||
gulong *cardinals;
|
||||
int n_cardinals;
|
||||
uint32_t *cardinals;
|
||||
int n_cardinals;
|
||||
} cardinal_list;
|
||||
|
||||
struct
|
||||
@@ -204,8 +170,8 @@ typedef struct
|
||||
|
||||
struct
|
||||
{
|
||||
Atom *atoms;
|
||||
int n_atoms;
|
||||
uint32_t *atoms;
|
||||
int n_atoms;
|
||||
} atom_list;
|
||||
|
||||
} v;
|
||||
|
Reference in New Issue
Block a user