winehq.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
January
2003
December
November
October
September
August
July
June
May
April
March
February
January
2002
December
November
October
September
August
July
June
May
April
March
February
January
2001
December
November
October
September
August
July
June
May
April
March
February
List overview
wine-commits
September 2023
----- 2025 -----
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
January 2004
----- 2003 -----
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
----- 2002 -----
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
January 2002
----- 2001 -----
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
wine-commits@winehq.org
1 participants
920 discussions
Start a n
N
ew thread
Paul Gofman : winegstreamer: Also return output with 2 channels for multichannel inputs from AAC decoder.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 416a273241e6eb7a8d15380387fef00e159b7277 URL:
https://gitlab.winehq.org/wine/wine/-/commit/416a273241e6eb7a8d15380387fef0…
Author: Paul Gofman <pgofman(a)codeweavers.com> Date: Mon Sep 18 20:05:21 2023 -0600 winegstreamer: Also return output with 2 channels for multichannel inputs from AAC decoder. --- dlls/mf/tests/transform.c | 2 +- dlls/winegstreamer/aac_decoder.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 787f7663d84..c5ef1f5960a 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -2649,7 +2649,7 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de } ok(hr == MF_E_NO_MORE_TYPES, "got %#lx.\n", hr); if (many_channels) - todo_wine ok(i == ARRAY_SIZE(expect_available_outputs) * 2, "got %lu media types.\n", i); + ok(i == ARRAY_SIZE(expect_available_outputs) * 2, "got %lu media types.\n", i); else ok(i == ARRAY_SIZE(expect_available_outputs), "got %lu media types.\n", i); winetest_pop_context(); diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index 35689a49c38..3eb96d0106a 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -311,6 +311,14 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR if (channel_count >= ARRAY_SIZE(default_channel_mask)) return MF_E_INVALIDMEDIATYPE; + if (channel_count > 2 && index >= ARRAY_SIZE(aac_decoder_output_types)) + { + /* If there are more than two channels in the input type GetOutputAvailableType additionally lists + * types with 2 channels. */ + index -= ARRAY_SIZE(aac_decoder_output_types); + channel_count = 2; + } + if (index >= ARRAY_SIZE(aac_decoder_output_types)) return MF_E_NO_MORE_TYPES; index = ARRAY_SIZE(aac_decoder_output_types) - index - 1;
1
0
0
0
Paul Gofman : winegstreamer: Validate maximum channel count in _SetInputType in AAC decoder.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: bb95f8c2f6fd46e922debcefc7a05509acdc48e9 URL:
https://gitlab.winehq.org/wine/wine/-/commit/bb95f8c2f6fd46e922debcefc7a055…
Author: Paul Gofman <pgofman(a)codeweavers.com> Date: Mon Sep 18 20:28:15 2023 -0600 winegstreamer: Validate maximum channel count in _SetInputType in AAC decoder. --- dlls/mf/tests/transform.c | 2 +- dlls/winegstreamer/aac_decoder.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index eadde5237f0..787f7663d84 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -2586,7 +2586,7 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de ok(hr == S_OK, "got %#lx.\n", hr); else { - todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "got %#lx.\n", hr); + ok(hr == MF_E_INVALIDMEDIATYPE, "got %#lx.\n", hr); winetest_pop_context(); continue; } diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index cdd4cc18477..35689a49c38 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -374,6 +374,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM { struct aac_decoder *decoder = impl_from_IMFTransform(iface); MF_ATTRIBUTE_TYPE item_type; + UINT32 channel_count; GUID major, subtype; HRESULT hr; ULONG i; @@ -396,6 +397,10 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (i == ARRAY_SIZE(aac_decoder_input_types)) return MF_E_INVALIDMEDIATYPE; + if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count)) + && channel_count >= ARRAY_SIZE(default_channel_mask)) + return MF_E_INVALIDMEDIATYPE; + if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &item_type)) || item_type != MF_ATTRIBUTE_UINT32) return MF_E_INVALIDMEDIATYPE;
1
0
0
0
Paul Gofman : winegstreamer: Correct output available types attrs in AAC decoder for channel count > 2.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 902133b0086307b5e2b33818dd0b22a95568206c URL:
https://gitlab.winehq.org/wine/wine/-/commit/902133b0086307b5e2b33818dd0b22…
Author: Paul Gofman <pgofman(a)codeweavers.com> Date: Mon Sep 18 20:00:41 2023 -0600 winegstreamer: Correct output available types attrs in AAC decoder for channel count > 2. --- dlls/mf/tests/transform.c | 4 +--- dlls/winegstreamer/aac_decoder.c | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 02eaab25f14..eadde5237f0 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -2622,7 +2622,7 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, &value); if (many_channels && i < ARRAY_SIZE(expect_available_outputs)) { - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "got %#lx.\n", hr); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "got %#lx.\n", hr); } else { @@ -2638,11 +2638,9 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de } else { - todo_wine { ok(hr == S_OK, "got %#lx.\n", hr); ok(value == expected_mask[expected_chans], "got %#x, expected %#x.\n", value, expected_mask[expected_chans]); - } } ret = IMFMediaType_Release(type); diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index ea03d95305b..cdd4cc18477 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -24,6 +24,8 @@ #include "mfobjects.h" #include "mftransform.h" #include "wmcodecdsp.h" +#include "ks.h" +#include "ksmedia.h" #include "wine/debug.h" @@ -48,6 +50,17 @@ static const GUID *const aac_decoder_output_types[] = &MFAudioFormat_Float, }; +static const UINT32 default_channel_mask[7] = +{ + 0, + 0, + 0, + SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_CENTER, + KSAUDIO_SPEAKER_QUAD, + KSAUDIO_SPEAKER_QUAD | SPEAKER_FRONT_CENTER, + KSAUDIO_SPEAKER_5POINT1, +}; + struct aac_decoder { IMFTransform IMFTransform_iface; @@ -295,6 +308,9 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR || !channel_count) channel_count = 2; + if (channel_count >= ARRAY_SIZE(default_channel_mask)) + return MF_E_INVALIDMEDIATYPE; + if (index >= ARRAY_SIZE(aac_decoder_output_types)) return MF_E_NO_MORE_TYPES; index = ARRAY_SIZE(aac_decoder_output_types) - index - 1; @@ -340,7 +356,10 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR goto done; if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1))) goto done; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1))) + if (channel_count < 3 && FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1))) + goto done; + if (channel_count >= 3 && FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_CHANNEL_MASK, + default_channel_mask[channel_count]))) goto done; done:
1
0
0
0
Paul Gofman : winegstreamer: Handle missing or zero channel count in _GetOutputAvailableType in AAC decoder.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 5b0172e1617051b0c0cddb96b66b9f9b48e1d6e4 URL:
https://gitlab.winehq.org/wine/wine/-/commit/5b0172e1617051b0c0cddb96b66b9f…
Author: Paul Gofman <pgofman(a)codeweavers.com> Date: Mon Sep 18 19:22:37 2023 -0600 winegstreamer: Handle missing or zero channel count in _GetOutputAvailableType in AAC decoder. --- dlls/mf/tests/transform.c | 19 ++++++++++++++++--- dlls/winegstreamer/aac_decoder.c | 6 ++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index e6ccb98e9ed..02eaab25f14 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -2555,6 +2555,22 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de goto failed; } + hr = MFCreateMediaType(&type); + ok(hr == S_OK, "got %#lx.\n", hr); + input_desc[num_channels_index].value.vt = VT_UI8; + input_desc[num_channels_index].value.ulVal = 1; + init_media_type(type, input_desc, -1); + hr = IMFTransform_SetInputType(transform, 0, type, 0); + ok(hr == S_OK, "got %#lx.\n", hr); + IMFMediaType_Release(type); + hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &type); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IMFAttributes_GetUINT32((IMFAttributes *)type, &MF_MT_AUDIO_NUM_CHANNELS, &value); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(value == 2, "got %u.\n", value); + IMFMediaType_Release(type); + input_desc[num_channels_index].value.vt = VT_UI4; + for (num_channels = 0; num_channels < 16; ++num_channels) { many_channels = num_channels > 2; @@ -2592,18 +2608,15 @@ static void test_aac_decoder_channels(const struct attribute_desc *input_type_de expected_chans = 2; else expected_chans = num_channels; - todo_wine_if(!num_channels) ok(value == expected_chans, "got %u, expected %u.\n", value, expected_chans); hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &value); ok(hr == S_OK, "got %#lx.\n", hr); - todo_wine_if(!num_channels) ok(value == sample_size * 44100 * expected_chans, "got %u, expected %u.\n", value, sample_size * 44100 * expected_chans); hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &value); ok(hr == S_OK, "got %#lx.\n", hr); - todo_wine_if(!num_channels) ok(value == sample_size * expected_chans, "got %u, expected %u.\n", value, sample_size * expected_chans); hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, &value); diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index 3588d00a28c..ea03d95305b 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -291,6 +291,10 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR *type = NULL; + if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count)) + || !channel_count) + channel_count = 2; + if (index >= ARRAY_SIZE(aac_decoder_output_types)) return MF_E_NO_MORE_TYPES; index = ARRAY_SIZE(aac_decoder_output_types) - index - 1; @@ -318,8 +322,6 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size))) goto done; - if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count))) - goto done; if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channel_count))) goto done;
1
0
0
0
Paul Gofman : mf/tests: Add tests for AAC decoder with different input number of channels.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 3432ef30c302a8dae50731c0e9621a2070258462 URL:
https://gitlab.winehq.org/wine/wine/-/commit/3432ef30c302a8dae50731c0e9621a…
Author: Paul Gofman <pgofman(a)codeweavers.com> Date: Mon Sep 18 19:10:05 2023 -0600 mf/tests: Add tests for AAC decoder with different input number of channels. --- dlls/mf/tests/transform.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 87dcf7f0814..e6ccb98e9ed 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -36,6 +36,8 @@ #include "mediaerr.h" #include "amvideo.h" #include "vfw.h" +#include "ks.h" +#include "ksmedia.h" #include "mf_test.h" @@ -2487,6 +2489,169 @@ failed: CoUninitialize(); } +static void test_aac_decoder_channels(const struct attribute_desc *input_type_desc) +{ + static const struct attribute_desc expect_output_attributes[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + {0}, + }; + static const media_type_desc expect_available_outputs[] = + { + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + }, + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), + }, + }; + static const UINT32 expected_mask[7] = + { + 0, + 0, + 0, + SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_CENTER, + KSAUDIO_SPEAKER_QUAD, + KSAUDIO_SPEAKER_QUAD | SPEAKER_FRONT_CENTER, + KSAUDIO_SPEAKER_5POINT1, + }; + + UINT32 value, num_channels, expected_chans, format_index, sample_size; + unsigned int num_channels_index = ~0u; + struct attribute_desc input_desc[64]; + IMFTransform *transform; + IMFAttributes *attrs; + IMFMediaType *type; + BOOL many_channels; + ULONG i, ret; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(input_desc); i++) + { + input_desc[i] = input_type_desc[i]; + if (!input_desc[i].key) + break; + if (IsEqualGUID(input_desc[i].key, &MF_MT_AUDIO_NUM_CHANNELS)) + num_channels_index = i; + } + + ok(num_channels_index != ~0u, "Could not find MF_MT_AUDIO_NUM_CHANNELS.\n"); + ok(i < ARRAY_SIZE(input_desc), "Too many attributes.\n"); + + hr = CoInitialize(NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + winetest_push_context("aacdec channels"); + + if (FAILED(hr = CoCreateInstance(&CLSID_MSAACDecMFT, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform))) + { + win_skip("AAC decoder transform is not available.\n"); + goto failed; + } + + for (num_channels = 0; num_channels < 16; ++num_channels) + { + many_channels = num_channels > 2; + winetest_push_context("chans %u", num_channels); + input_desc[num_channels_index].value.ulVal = num_channels; + + hr = MFCreateMediaType(&type); + ok(hr == S_OK, "got %#lx.\n", hr); + init_media_type(type, input_desc, -1); + hr = IMFTransform_SetInputType(transform, 0, type, 0); + IMFMediaType_Release(type); + if (num_channels <= 6) + ok(hr == S_OK, "got %#lx.\n", hr); + else + { + todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "got %#lx.\n", hr); + winetest_pop_context(); + continue; + } + + i = -1; + while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &type))) + { + winetest_push_context("out %lu", i); + ok(hr == S_OK, "got %#lx.\n", hr); + check_media_type(type, expect_output_attributes, -1); + format_index = i % 2; + sample_size = format_index ? 2 : 4; + check_media_type(type, expect_available_outputs[format_index], -1); + attrs = (IMFAttributes *)type; + + hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_NUM_CHANNELS, &value); + ok(hr == S_OK, "got %#lx.\n", hr); + if (!num_channels || i >= ARRAY_SIZE(expect_available_outputs)) + expected_chans = 2; + else + expected_chans = num_channels; + todo_wine_if(!num_channels) + ok(value == expected_chans, "got %u, expected %u.\n", value, expected_chans); + + hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &value); + ok(hr == S_OK, "got %#lx.\n", hr); + todo_wine_if(!num_channels) + ok(value == sample_size * 44100 * expected_chans, "got %u, expected %u.\n", + value, sample_size * 44100 * expected_chans); + + hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &value); + ok(hr == S_OK, "got %#lx.\n", hr); + todo_wine_if(!num_channels) + ok(value == sample_size * expected_chans, "got %u, expected %u.\n", value, sample_size * expected_chans); + + hr = IMFAttributes_GetUINT32(attrs, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, &value); + if (many_channels && i < ARRAY_SIZE(expect_available_outputs)) + { + todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "got %#lx.\n", hr); + } + else + { + ok(hr == S_OK, "got %#lx.\n", hr); + ok(value == 1, "got %u.\n", value); + } + + value = 0xdeadbeef; + hr = IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &value); + if (expected_chans <= 2) + { + ok(hr == MF_E_ATTRIBUTENOTFOUND, "got %#lx.\n", hr); + } + else + { + todo_wine { + ok(hr == S_OK, "got %#lx.\n", hr); + ok(value == expected_mask[expected_chans], "got %#x, expected %#x.\n", + value, expected_mask[expected_chans]); + } + } + + ret = IMFMediaType_Release(type); + ok(ret <= 1, "got %lu.\n", ret); + winetest_pop_context(); + } + ok(hr == MF_E_NO_MORE_TYPES, "got %#lx.\n", hr); + if (many_channels) + todo_wine ok(i == ARRAY_SIZE(expect_available_outputs) * 2, "got %lu media types.\n", i); + else + ok(i == ARRAY_SIZE(expect_available_outputs), "got %lu media types.\n", i); + winetest_pop_context(); + } + + ret = IMFTransform_Release(transform); + ok(!ret, "got %lu.\n", ret); + +failed: + winetest_pop_context(); + CoUninitialize(); +} + static void test_aac_decoder(void) { static const BYTE aac_raw_codec_data[] = {0x12, 0x08}; @@ -2515,6 +2680,9 @@ static void test_aac_decoder(void) test_aac_decoder_subtype(aac_input_type_desc); test_aac_decoder_subtype(raw_aac_input_type_desc); + + test_aac_decoder_channels(aac_input_type_desc); + test_aac_decoder_channels(raw_aac_input_type_desc); } static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
1
0
0
0
Alexandros Frantzis : winewayland.drv: Fix removal of wl_seat globals.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: d7ec8fb6a3ce6b70646c3dfa51be1fb68364a782 URL:
https://gitlab.winehq.org/wine/wine/-/commit/d7ec8fb6a3ce6b70646c3dfa51be1f…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com> Date: Fri Sep 22 14:00:03 2023 +0300 winewayland.drv: Fix removal of wl_seat globals. Store and compare against the wl_seat global id (aka name) during global_remove, since the global id is distinct from the wl_proxy id which we were previously checking. --- dlls/winewayland.drv/wayland.c | 5 +++-- dlls/winewayland.drv/waylanddrv.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 700eb41fee7..b8c69a105cb 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -134,6 +134,7 @@ static void registry_handle_global(void *data, struct wl_registry *registry, pthread_mutex_lock(&seat->mutex); seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, version < 5 ? version : 5); + seat->global_id = id; wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); pthread_mutex_unlock(&seat->mutex); } @@ -158,14 +159,14 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist } seat = &process_wayland.seat; - if (seat->wl_seat && - wl_proxy_get_id((struct wl_proxy *)seat->wl_seat) == id) + if (seat->wl_seat && seat->global_id == id) { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); pthread_mutex_lock(&seat->mutex); wl_seat_release(seat->wl_seat); seat->wl_seat = NULL; + seat->global_id = 0; pthread_mutex_unlock(&seat->mutex); } } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4c6eb170900..faff529940d 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -83,6 +83,7 @@ struct wayland_pointer struct wayland_seat { struct wl_seat *wl_seat; + uint32_t global_id; pthread_mutex_t mutex; };
1
0
0
0
Alexandros Frantzis : winewayland.drv: Handle client-initiated user-driven window resize.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 24a6f36784e2e60e2fddfd1ba1ed1da301ab1ea3 URL:
https://gitlab.winehq.org/wine/wine/-/commit/24a6f36784e2e60e2fddfd1ba1ed1d…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com> Date: Mon Sep 18 13:58:31 2023 +0300 winewayland.drv: Handle client-initiated user-driven window resize. When we are notified by Wine core that the user wants to interactively resize the window, forward the request to compositor, so it can take over and resize the window according to user input. In the process of the interactive resize we receive a stream of xdg_toplevel configure events informing us about the updated window sizes. --- dlls/winewayland.drv/wayland_surface.c | 3 +++ dlls/winewayland.drv/waylanddrv.h | 9 ++++++- dlls/winewayland.drv/window.c | 47 ++++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 9514106d0d1..8551ad98eeb 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -88,6 +88,9 @@ static void xdg_toplevel_handle_configure(void *data, case XDG_TOPLEVEL_STATE_MAXIMIZED: config_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; break; + case XDG_TOPLEVEL_STATE_RESIZING: + config_state |= WAYLAND_SURFACE_CONFIG_STATE_RESIZING; + break; default: break; } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index bb78883c539..4c6eb170900 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -59,7 +59,8 @@ enum wayland_window_message enum wayland_surface_config_state { - WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0) + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0), + WAYLAND_SURFACE_CONFIG_STATE_RESIZING = (1 << 1) }; struct wayland_cursor @@ -147,6 +148,7 @@ struct wayland_surface pthread_mutex_t mutex; struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; + BOOL resizing; }; struct wayland_shm_buffer @@ -228,6 +230,11 @@ static inline BOOL intersect_rect(RECT *dst, const RECT *src1, const RECT *src2) return !IsRectEmpty(dst); } +static inline LRESULT send_message(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + return NtUserMessageCall(hwnd, msg, wparam, lparam, NULL, NtUserSendMessage, FALSE); +} + RGNDATA *get_region_data(HRGN region) DECLSPEC_HIDDEN; /********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 881ba24d01d..5079d820929 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -335,6 +335,8 @@ static void wayland_configure_window(HWND hwnd) UINT flags; uint32_t state; DWORD style; + BOOL needs_enter_size_move = FALSE; + BOOL needs_exit_size_move = FALSE; if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; @@ -359,10 +361,25 @@ static void wayland_configure_window(HWND hwnd) height = surface->processing.height; state = surface->processing.state; + if ((state & WAYLAND_SURFACE_CONFIG_STATE_RESIZING) && !surface->resizing) + { + surface->resizing = TRUE; + needs_enter_size_move = TRUE; + } + + if (!(state & WAYLAND_SURFACE_CONFIG_STATE_RESIZING) && surface->resizing) + { + surface->resizing = FALSE; + needs_exit_size_move = TRUE; + } + pthread_mutex_unlock(&surface->mutex); TRACE("processing=%dx%d,%#x\n", width, height, state); + if (needs_enter_size_move) send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0); + if (needs_exit_size_move) send_message(hwnd, WM_EXITSIZEMOVE, 0, 0); + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; if (width == 0 || height == 0) flags |= SWP_NOSIZE; @@ -415,6 +432,22 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); } +static enum xdg_toplevel_resize_edge hittest_to_resize_edge(WPARAM hittest) +{ + switch (hittest) + { + case WMSZ_LEFT: return XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + case WMSZ_RIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + case WMSZ_TOP: return XDG_TOPLEVEL_RESIZE_EDGE_TOP; + case WMSZ_TOPLEFT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + case WMSZ_TOPRIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + case WMSZ_BOTTOM: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + case WMSZ_BOTTOMLEFT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + case WMSZ_BOTTOMRIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + default: return XDG_TOPLEVEL_RESIZE_EDGE_NONE; + } +} + /*********************************************************************** * WAYLAND_SysCommand */ @@ -436,14 +469,24 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) button_serial = 0; pthread_mutex_unlock(&process_wayland.pointer.mutex); - if (command == SC_MOVE) + if (command == SC_MOVE || command == SC_SIZE) { if ((surface = wayland_surface_lock_hwnd(hwnd))) { pthread_mutex_lock(&process_wayland.seat.mutex); wl_seat = process_wayland.seat.wl_seat; if (wl_seat && surface->xdg_toplevel && button_serial) - xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + { + if (command == SC_MOVE) + { + xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + } + else if (command == SC_SIZE) + { + xdg_toplevel_resize(surface->xdg_toplevel, wl_seat, button_serial, + hittest_to_resize_edge(wparam & 0x0f)); + } + } pthread_mutex_unlock(&process_wayland.seat.mutex); pthread_mutex_unlock(&surface->mutex); ret = 0;
1
0
0
0
Alexandros Frantzis : winewayland.drv: Handle client-initiated user-driven window move.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: ddc4cfe238bae4c2ad86c6e06cd10c80c3d2b803 URL:
https://gitlab.winehq.org/wine/wine/-/commit/ddc4cfe238bae4c2ad86c6e06cd10c…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com> Date: Mon Sep 18 13:02:06 2023 +0300 winewayland.drv: Handle client-initiated user-driven window move. When we are notified by Wine core that the user wants to interactively move the window, forward the request to compositor, so it can take over and move the window according to user input. Note that the move does *not* affect the position of the window in the Wine virtual screen space. --- dlls/winewayland.drv/wayland.c | 24 ++++++++++++++------- dlls/winewayland.drv/wayland_pointer.c | 6 ++++++ dlls/winewayland.drv/waylanddrv.h | 10 ++++++++- dlls/winewayland.drv/waylanddrv_main.c | 1 + dlls/winewayland.drv/window.c | 39 ++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 51e36b5ba60..700eb41fee7 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -34,6 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv); struct wayland process_wayland = { + .seat.mutex = PTHREAD_MUTEX_INITIALIZER, .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, .output_mutex = PTHREAD_MUTEX_INITIALIZER @@ -124,14 +125,17 @@ static void registry_handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, "wl_seat") == 0) { - if (process_wayland.wl_seat) + struct wayland_seat *seat = &process_wayland.seat; + if (seat->wl_seat) { WARN("Only a single seat is currently supported, ignoring additional seats.\n"); return; } - process_wayland.wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, - version < 5 ? version : 5); - wl_seat_add_listener(process_wayland.wl_seat, &seat_listener, NULL); + pthread_mutex_lock(&seat->mutex); + seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, + version < 5 ? version : 5); + wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); + pthread_mutex_unlock(&seat->mutex); } } @@ -139,6 +143,7 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist uint32_t id) { struct wayland_output *output, *tmp; + struct wayland_seat *seat; TRACE("id=%u\n", id); @@ -152,13 +157,16 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist } } - if (process_wayland.wl_seat && - wl_proxy_get_id((struct wl_proxy *)process_wayland.wl_seat) == id) + seat = &process_wayland.seat; + if (seat->wl_seat && + wl_proxy_get_id((struct wl_proxy *)seat->wl_seat) == id) { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); - wl_seat_release(process_wayland.wl_seat); - process_wayland.wl_seat = NULL; + pthread_mutex_lock(&seat->mutex); + wl_seat_release(seat->wl_seat); + seat->wl_seat = NULL; + pthread_mutex_unlock(&seat->mutex); } } diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 69f3a7c16a7..ff376882d73 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -129,6 +129,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + struct wayland_pointer *pointer = &process_wayland.pointer; INPUT input = {0}; HWND hwnd; @@ -146,6 +147,11 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, if (state == WL_POINTER_BUTTON_STATE_RELEASED) input.mi.dwFlags <<= 1; + pthread_mutex_lock(&pointer->mutex); + pointer->button_serial = state == WL_POINTER_BUTTON_STATE_PRESSED ? + serial : 0; + pthread_mutex_unlock(&pointer->mutex); + TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state); __wine_send_input(hwnd, &input, NULL); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 51e958c85f8..bb78883c539 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -74,10 +74,17 @@ struct wayland_pointer struct wl_pointer *wl_pointer; HWND focused_hwnd; uint32_t enter_serial; + uint32_t button_serial; struct wayland_cursor cursor; pthread_mutex_t mutex; }; +struct wayland_seat +{ + struct wl_seat *wl_seat; + pthread_mutex_t mutex; +}; + struct wayland { BOOL initialized; @@ -88,7 +95,7 @@ struct wayland struct wl_compositor *wl_compositor; struct xdg_wm_base *xdg_wm_base; struct wl_shm *wl_shm; - struct wl_seat *wl_seat; + struct wayland_seat seat; struct wayland_pointer pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ @@ -230,6 +237,7 @@ RGNDATA *get_region_data(HRGN region) DECLSPEC_HIDDEN; LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; void WAYLAND_DestroyWindow(HWND hwnd) DECLSPEC_HIDDEN; void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor) DECLSPEC_HIDDEN; +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) DECLSPEC_HIDDEN; BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manager, BOOL force, void *param) DECLSPEC_HIDDEN; LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index eb54efe1180..7151d7b931a 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -34,6 +34,7 @@ static const struct user_driver_funcs waylanddrv_funcs = .pDesktopWindowProc = WAYLAND_DesktopWindowProc, .pDestroyWindow = WAYLAND_DestroyWindow, .pSetCursor = WAYLAND_SetCursor, + .pSysCommand = WAYLAND_SysCommand, .pUpdateDisplayDevices = WAYLAND_UpdateDisplayDevices, .pWindowMessage = WAYLAND_WindowMessage, .pWindowPosChanged = WAYLAND_WindowPosChanged, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 194568e0228..881ba24d01d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -415,6 +415,45 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); } +/*********************************************************************** + * WAYLAND_SysCommand + */ +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) +{ + LRESULT ret = -1; + WPARAM command = wparam & 0xfff0; + uint32_t button_serial; + struct wl_seat *wl_seat; + struct wayland_surface *surface; + + TRACE("cmd=%lx hwnd=%p, %lx, %lx\n", + (long)command, hwnd, (long)wparam, lparam); + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if (process_wayland.pointer.focused_hwnd == hwnd) + button_serial = process_wayland.pointer.button_serial; + else + button_serial = 0; + pthread_mutex_unlock(&process_wayland.pointer.mutex); + + if (command == SC_MOVE) + { + if ((surface = wayland_surface_lock_hwnd(hwnd))) + { + pthread_mutex_lock(&process_wayland.seat.mutex); + wl_seat = process_wayland.seat.wl_seat; + if (wl_seat && surface->xdg_toplevel && button_serial) + xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + pthread_mutex_unlock(&process_wayland.seat.mutex); + pthread_mutex_unlock(&surface->mutex); + ret = 0; + } + } + + wl_display_flush(process_wayland.wl_display); + return ret; +} + /********************************************************************** * wayland_window_flush *
1
0
0
0
Alexandros Frantzis : winewayland.drv: Handle xdg_toplevel maximized state.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 36ecb876dbc10151d62e35d009a310d59fed07e6 URL:
https://gitlab.winehq.org/wine/wine/-/commit/36ecb876dbc10151d62e35d009a310…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com> Date: Mon Sep 18 09:57:12 2023 +0300 winewayland.drv: Handle xdg_toplevel maximized state. A request for the maximized state has two potential origins: 1. The compositor, through an xdg_toplevel configure event. In this case we update the window state and size accordingly. 2. The application or Wine itself, by changing the window style. When we detect such a style, we make a request to the compositor to set the maximized state. The compositor will then eventually reply with a configure event, and we continue with case (1). Note that the compositor may deny our request, in which case we will also sync the window style accordingly. An acknowledged maximized state imposes very strict constraints on the size of surface content we can present. We are careful to not violate these constraints, since otherwise the compositor will disconnect us. --- dlls/winewayland.drv/wayland_surface.c | 88 +++++++++++++++++++++++++++++----- dlls/winewayland.drv/waylanddrv.h | 6 +++ dlls/winewayland.drv/window.c | 41 +++++++++++++++- 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0004e51fe0f..9514106d0d1 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -78,8 +78,22 @@ static void xdg_toplevel_handle_configure(void *data, { struct wayland_surface *surface; HWND hwnd = data; + uint32_t *state; + enum wayland_surface_config_state config_state = 0; - TRACE("hwnd=%p %dx%d\n", hwnd, width, height); + wl_array_for_each(state, states) + { + switch(*state) + { + case XDG_TOPLEVEL_STATE_MAXIMIZED: + config_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; + break; + default: + break; + } + } + + TRACE("hwnd=%p %dx%d,%#x\n", hwnd, width, height, config_state); if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; @@ -87,6 +101,7 @@ static void xdg_toplevel_handle_configure(void *data, { surface->pending.width = width; surface->pending.height = height; + surface->pending.state = config_state; } pthread_mutex_unlock(&surface->mutex); @@ -291,6 +306,32 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, } } +/********************************************************************** + * wayland_surface_configure_is_compatible + * + * Checks whether a wayland_surface_configure object is compatible with the + * the provided arguments. + */ +static BOOL wayland_surface_configure_is_compatible(struct wayland_surface_config *conf, + int width, int height, + enum wayland_surface_config_state state) +{ + static enum wayland_surface_config_state mask = + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; + + /* We require the same state. */ + if ((state & mask) != (conf->state & mask)) return FALSE; + + /* The maximized state requires the configured size. */ + if ((conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + (width != conf->width || height != conf->height)) + { + return FALSE; + } + + return TRUE; +} + /********************************************************************** * wayland_surface_reconfigure * @@ -299,27 +340,52 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, */ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) { - if (!surface->xdg_toplevel) return TRUE; + RECT window_rect; + int width, height; + enum wayland_surface_config_state window_state; - TRACE("hwnd=%p\n", surface->hwnd); - - /* Acknowledge any processed config. */ - if (surface->processing.serial && surface->processing.processed) + if (!surface->xdg_toplevel) return TRUE; + if (!NtUserGetWindowRect(surface->hwnd, &window_rect)) return FALSE; + + width = window_rect.right - window_rect.left; + height = window_rect.bottom - window_rect.top; + + window_state = + (NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ? + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; + + TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", + surface->hwnd, width, height, window_state, + surface->processing.width, surface->processing.height, + surface->processing.state, surface->current.width, + surface->current.height, surface->current.state); + + /* Acknowledge any compatible processed config. */ + if (surface->processing.serial && surface->processing.processed && + wayland_surface_configure_is_compatible(&surface->processing, + width, height, + window_state)) { surface->current = surface->processing; memset(&surface->processing, 0, sizeof(surface->processing)); xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } - /* If this is the initial configure, and we have a requested config, - * use that, in order to draw windows that don't go through the message - * loop (e.g., some splash screens). */ - else if (!surface->current.serial && surface->requested.serial) + /* If this is the initial configure, and we have a compatible requested + * config, use that, in order to draw windows that don't go through the + * message loop (e.g., some splash screens). */ + else if (!surface->current.serial && surface->requested.serial && + wayland_surface_configure_is_compatible(&surface->requested, + width, height, + window_state)) { surface->current = surface->requested; memset(&surface->requested, 0, sizeof(surface->requested)); xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } - else if (!surface->current.serial) + else if (!surface->current.serial || + !wayland_surface_configure_is_compatible(&surface->current, + width, height, + window_state)) { return FALSE; } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 5246d3ba9cb..51e958c85f8 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -57,6 +57,11 @@ enum wayland_window_message WM_WAYLAND_CONFIGURE = 0x80001001 }; +enum wayland_surface_config_state +{ + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0) +}; + struct wayland_cursor { struct wayland_shm_buffer *shm_buffer; @@ -121,6 +126,7 @@ struct wayland_output struct wayland_surface_config { int32_t width, height; + enum wayland_surface_config_state state; uint32_t serial; BOOL processed; }; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 86f4e30b136..194568e0228 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -195,15 +195,38 @@ out: static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) { struct wayland_surface *surface = data->wayland_surface; + uint32_t window_state; + struct wayland_surface_config *conf; pthread_mutex_lock(&surface->mutex); if (!surface->xdg_toplevel) goto out; - if (surface->processing.serial) surface->processing.processed = TRUE; + window_state = + (NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ? + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; + + conf = surface->processing.serial ? &surface->processing : &surface->current; + + TRACE("hwnd=%p window_state=%#x conf->state=%#x\n", + data->hwnd, window_state, conf->state); + + if ((window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + !(conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + { + xdg_toplevel_set_maximized(surface->xdg_toplevel); + } + else if (!(window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + (conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + { + xdg_toplevel_unset_maximized(surface->xdg_toplevel); + } + + conf->processed = TRUE; out: pthread_mutex_unlock(&surface->mutex); + wl_display_flush(process_wayland.wl_display); } /*********************************************************************** @@ -310,6 +333,8 @@ static void wayland_configure_window(HWND hwnd) struct wayland_surface *surface; INT width, height; UINT flags; + uint32_t state; + DWORD style; if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; @@ -332,12 +357,26 @@ static void wayland_configure_window(HWND hwnd) width = surface->processing.width; height = surface->processing.height; + state = surface->processing.state; pthread_mutex_unlock(&surface->mutex); + TRACE("processing=%dx%d,%#x\n", width, height, state); + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; if (width == 0 || height == 0) flags |= SWP_NOSIZE; + style = NtUserGetWindowLongW(hwnd, GWL_STYLE); + if (!(state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) != !(style & WS_MAXIMIZE)) + { + NtUserSetWindowLong(hwnd, GWL_STYLE, style ^ WS_MAXIMIZE, FALSE); + flags |= SWP_FRAMECHANGED; + } + + /* The Wayland maximized state is very strict about surface size, so don't + * let the application override it. */ + if (state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) flags |= SWP_NOSENDCHANGING; + NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); }
1
0
0
0
Alexandros Frantzis : winewayland.drv: Handle xdg_toplevel configure event size hint.
by Alexandre Julliard
27 Sep '23
27 Sep '23
Module: wine Branch: master Commit: 6e903b7924fb05806dca8c05c2c64034f953626f URL:
https://gitlab.winehq.org/wine/wine/-/commit/6e903b7924fb05806dca8c05c2c640…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com> Date: Wed Sep 13 11:32:20 2023 +0300 winewayland.drv: Handle xdg_toplevel configure event size hint. Use the size hint provided by the compositor to resize the window associated with a Wayland toplevel surface. A surface config moves through the following stages (each stage may hold a different event): 1. Pending: In the process of being populated from separate Wayland events. 2. Requested: A fully formed config which hasn't been handled yet. A new finalized Pending event will always be promoted to a Requested event (so we will skip previous events if new ones arrive quickly enough). 3. Processing: A config that is being processed. When processing is done, we mark it with `wayland_surface_config.processed = TRUE`. 4. Current: The config has been acknowledged, i.e., we are promising to respect any implied content constraints. --- dlls/winewayland.drv/wayland_surface.c | 67 ++++++++++++++++++++++++++++++++-- dlls/winewayland.drv/waylanddrv.h | 13 ++++++- dlls/winewayland.drv/window.c | 54 +++++++++++++++++++++++++++ dlls/winewayland.drv/window_surface.c | 2 +- 4 files changed, 129 insertions(+), 7 deletions(-) diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 832a1081234..0004e51fe0f 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -48,9 +48,15 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur * the target xdg_surface. */ if (surface->xdg_surface == xdg_surface) { - initial_configure = surface->current_serial == 0; - surface->current_serial = serial; - xdg_surface_ack_configure(xdg_surface, serial); + /* If we have a previously requested config, we have already sent a + * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case, + * avoid sending another message to reduce message queue traffic. */ + BOOL should_post = surface->requested.serial == 0; + initial_configure = surface->current.serial == 0; + surface->pending.serial = serial; + surface->requested = surface->pending; + memset(&surface->pending, 0, sizeof(surface->pending)); + if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0); } pthread_mutex_unlock(&surface->mutex); @@ -70,6 +76,20 @@ static void xdg_toplevel_handle_configure(void *data, int32_t width, int32_t height, struct wl_array *states) { + struct wayland_surface *surface; + HWND hwnd = data; + + TRACE("hwnd=%p %dx%d\n", hwnd, width, height); + + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + + if (surface->xdg_toplevel == xdg_toplevel) + { + surface->pending.width = width; + surface->pending.height = height; + } + + pthread_mutex_unlock(&surface->mutex); } static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) @@ -217,7 +237,10 @@ void wayland_surface_clear_role(struct wayland_surface *surface) surface->xdg_surface = NULL; } - surface->current_serial = 0; + memset(&surface->pending, 0, sizeof(surface->pending)); + memset(&surface->requested, 0, sizeof(surface->requested)); + memset(&surface->processing, 0, sizeof(surface->processing)); + memset(&surface->current, 0, sizeof(surface->current)); /* Ensure no buffer is attached, otherwise future role assignments may fail. */ wl_surface_attach(surface->wl_surface, NULL, 0, 0); @@ -268,6 +291,42 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, } } +/********************************************************************** + * wayland_surface_reconfigure + * + * Reconfigures the wayland surface as needed to match the latest requested + * state. + */ +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) +{ + if (!surface->xdg_toplevel) return TRUE; + + TRACE("hwnd=%p\n", surface->hwnd); + + /* Acknowledge any processed config. */ + if (surface->processing.serial && surface->processing.processed) + { + surface->current = surface->processing; + memset(&surface->processing, 0, sizeof(surface->processing)); + xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); + } + /* If this is the initial configure, and we have a requested config, + * use that, in order to draw windows that don't go through the message + * loop (e.g., some splash screens). */ + else if (!surface->current.serial && surface->requested.serial) + { + surface->current = surface->requested; + memset(&surface->requested, 0, sizeof(surface->requested)); + xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); + } + else if (!surface->current.serial) + { + return FALSE; + } + + return TRUE; +} + /********************************************************************** * wayland_shm_buffer_ref * diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 6e0b5c6fb10..5246d3ba9cb 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -53,7 +53,8 @@ extern struct wayland process_wayland DECLSPEC_HIDDEN; enum wayland_window_message { - WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000 + WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000, + WM_WAYLAND_CONFIGURE = 0x80001001 }; struct wayland_cursor @@ -117,6 +118,13 @@ struct wayland_output struct wayland_output_state current; }; +struct wayland_surface_config +{ + int32_t width, height; + uint32_t serial; + BOOL processed; +}; + struct wayland_surface { HWND hwnd; @@ -124,7 +132,7 @@ struct wayland_surface struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; pthread_mutex_t mutex; - uint32_t current_serial; + struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; }; @@ -167,6 +175,7 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region) DECLSPEC_HIDDEN; struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN; +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) DECLSPEC_HIDDEN; /********************************************************************** * Wayland SHM buffer diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 958bc5dbe68..86f4e30b136 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -192,6 +192,20 @@ out: data->wayland_surface = surface; } +static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) +{ + struct wayland_surface *surface = data->wayland_surface; + + pthread_mutex_lock(&surface->mutex); + + if (!surface->xdg_toplevel) goto out; + + if (surface->processing.serial) surface->processing.processed = TRUE; + +out: + pthread_mutex_unlock(&surface->mutex); +} + /*********************************************************************** * WAYLAND_DestroyWindow */ @@ -276,6 +290,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, data->window_surface = surface; wayland_win_data_update_wayland_surface(data); + if (data->wayland_surface) wayland_win_data_update_wayland_state(data); wayland_win_data_release(data); } @@ -290,6 +305,42 @@ static void wayland_resize_desktop(void) SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); } +static void wayland_configure_window(HWND hwnd) +{ + struct wayland_surface *surface; + INT width, height; + UINT flags; + + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + + if (!surface->xdg_toplevel) + { + TRACE("missing xdg_toplevel, returning"); + pthread_mutex_unlock(&surface->mutex); + return; + } + + if (!surface->requested.serial) + { + TRACE("requested configure event already handled, returning\n"); + pthread_mutex_unlock(&surface->mutex); + return; + } + + surface->processing = surface->requested; + memset(&surface->requested, 0, sizeof(surface->requested)); + + width = surface->processing.width; + height = surface->processing.height; + + pthread_mutex_unlock(&surface->mutex); + + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; + if (width == 0 || height == 0) flags |= SWP_NOSIZE; + + NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); +} + /********************************************************************** * WAYLAND_WindowMessage */ @@ -301,6 +352,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) wayland_init_display_devices(TRUE); wayland_resize_desktop(); return 0; + case WM_WAYLAND_CONFIGURE: + wayland_configure_window(hwnd); + return 0; default: FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); return 0; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index baf2c12a922..67cb2fe2d0b 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -444,7 +444,7 @@ static void wayland_window_surface_flush(struct window_surface *window_surface) wayland_window_surface_copy_to_buffer(wws, shm_buffer, copy_from_window_region); pthread_mutex_lock(&wws->wayland_surface->mutex); - if (wws->wayland_surface->current_serial) + if (wayland_surface_reconfigure(wws->wayland_surface)) { wayland_surface_attach_shm(wws->wayland_surface, shm_buffer, surface_damage_region);
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
9
...
92
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
Results per page:
10
25
50
100
200