diff options
-rw-r--r-- | .SRCINFO | 24 | ||||
-rw-r--r-- | PKGBUILD | 51 | ||||
-rw-r--r-- | nine-1.8.patch (renamed from nine-1.8rc2.patch) | 449 | ||||
-rw-r--r-- | sni_support.patch | 2010 |
4 files changed, 20 insertions, 2514 deletions
@@ -1,8 +1,8 @@ # Generated by mksrcinfo v8 -# Sat Dec 19 10:26:08 UTC 2015 +# Wed Dec 23 13:01:48 UTC 2015 pkgbase = wine-gaming-nine pkgdesc = Based off wine-staging, including the gallium-nine patches and some more hacks - pkgver = 1.8rc4 + pkgver = 1.8 pkgrel = 1 url = http://www.wine-staging.com install = wine.install @@ -15,8 +15,8 @@ pkgbase = wine-gaming-nine makedepends = perl makedepends = fontforge makedepends = flex - makedepends = gcc>=4.5.0-2 - makedepends = gcc-multilib>=4.5.0-2 + makedepends = gcc>=5.3.0-3 + makedepends = gcc-multilib>=5.3.0-3 makedepends = giflib makedepends = lib32-giflib makedepends = libpng @@ -130,31 +130,29 @@ pkgbase = wine-gaming-nine optdepends = cups optdepends = samba optdepends = dosbox - provides = wine=1.8rc4 - provides = wine-wow64=1.8rc4 - provides = wine-staging=1.8rc4 + provides = wine=1.8 + provides = wine-wow64=1.8 + provides = wine-staging=1.8 conflicts = wine conflicts = wine-wow64 conflicts = wine-staging options = staticlibs - source = https://github.com/wine-compholio/wine-patched/archive/staging-1.8-rc4.tar.gz + source = https://github.com/wine-compholio/wine-patched/archive/staging-1.8.tar.gz source = 30-win32-aliases.conf source = hd7700m_support.patch source = heap_perf.patch source = keybindings.patch source = mipmap.patch - source = nine-1.8rc2.patch - source = sni_support.patch + source = nine-1.8.patch source = steam.patch source = wbemprox_query_v2.patch - sha1sums = 7d42649e4574056ba71c6c3fff82bf1fad492eb9 + sha1sums = 6aea600b850ac2ac4fed608d96c688c8d470222f sha1sums = 023a5c901c6a091c56e76b6a62d141d87cce9fdb sha1sums = 8fa4b03f68f18b4de80f10c7a43c0e99a5cb017c sha1sums = 0f4ac455436d5714a2cf0b537ed25f4fa5c1a7fd sha1sums = f3febb8836f38320742a546c667106608d4c4395 sha1sums = c3096fccbac23e520d03f592db7f23350cbbc0bc - sha1sums = 2ef0002b9db25f6014cca83c5176e3fad60e4233 - sha1sums = 8193eadee7de2a4d89abe7ca8dff43e877878a52 + sha1sums = a5832a96432979b6fc18019f931f80e4d3ecc240 sha1sums = a7da16c5fac7d74c665e7a76bddbcd6c8333830b sha1sums = e26d369e9964657b481ac4b7b18c575786ec9c8c @@ -6,12 +6,11 @@ # -Keybind patch reversion # -Heap allocation perfomance improvement patch # -Wbemprox videocontroller query fix v2 (see https://bugs.winehq.org/show_bug.cgi?id=38879 ) -# -SNI support (see https://bugs.winehq.org/show_bug.cgi?id=38409 ) # -Steam patch, Crossover Hack version (see https://bugs.winehq.org/show_bug.cgi?id=39403 ) # -HD7700M support (not referenced in Wine) pkgname=wine-gaming-nine -pkgver=1.8rc4 +pkgver=1.8 pkgrel=1 _pkgbasever=${pkgver/rc/-rc} @@ -23,19 +22,17 @@ source=("https://github.com/wine-compholio/wine-patched/archive/staging-$_pkgbas heap_perf.patch keybindings.patch mipmap.patch - nine-1.8rc2.patch - sni_support.patch + nine-1.8.patch steam.patch wbemprox_query_v2.patch ) -sha1sums=('7d42649e4574056ba71c6c3fff82bf1fad492eb9' +sha1sums=('6aea600b850ac2ac4fed608d96c688c8d470222f' '023a5c901c6a091c56e76b6a62d141d87cce9fdb' '8fa4b03f68f18b4de80f10c7a43c0e99a5cb017c' '0f4ac455436d5714a2cf0b537ed25f4fa5c1a7fd' 'f3febb8836f38320742a546c667106608d4c4395' 'c3096fccbac23e520d03f592db7f23350cbbc0bc' - '2ef0002b9db25f6014cca83c5176e3fad60e4233' - '8193eadee7de2a4d89abe7ca8dff43e877878a52' + 'a5832a96432979b6fc18019f931f80e4d3ecc240' 'a7da16c5fac7d74c665e7a76bddbcd6c8333830b' 'e26d369e9964657b481ac4b7b18c575786ec9c8c' ) @@ -66,7 +63,7 @@ _depends=( ) makedepends=(autoconf ncurses bison perl fontforge flex - 'gcc>=4.5.0-2' 'gcc-multilib>=4.5.0-2' + 'gcc>=5.3.0-3' 'gcc-multilib>=5.3.0-3' giflib lib32-giflib libpng lib32-libpng gnutls lib32-gnutls @@ -131,44 +128,15 @@ else conflicts=('wine' 'wine-wow64' 'wine-staging') fi -#Needed for testing gcc version -check_gcc() -{ - curver=($(gcc -dumpversion | sed 's/\./ /g')) - minver=(5 3 0) - - for ((i=${#curver[@]}; i<${#minver[@]}; i++)) - do - curver[i]=0 - done - - for ((i=0; i<${#curver[@]}; i++)) - do - if [[ -z ${minver[i]} ]] - then - minver[i]=0 - fi - - if [ "${curver[i]}" -lt "${minver[i]}" ]; then - return 1 - elif [ "${curver[i]}" -gt "${minver[i]}" ]; then - return 0 - fi - done - - return 0 -} - prepare() { cd wine-patched-staging-$_pkgbasever - patch -p1 < ../nine-1.8rc2.patch + patch -p1 < ../nine-1.8.patch patch -p1 < ../steam.patch patch -p1 < ../mipmap.patch patch -p1 < ../heap_perf.patch patch -p1 < ../wbemprox_query_v2.patch - patch -p1 < ../sni_support.patch patch -p1 < ../hd7700m_support.patch patch -p1 -R < ../keybindings.patch @@ -177,13 +145,6 @@ prepare() sed 's|OpenCL/opencl.h|CL/opencl.h|g' -i configure* - if [ ! check_gcc ]; then - # https://bugs.winehq.org/show_bug.cgi?id=38653 fixed sinced GCC 5.3.0 - echo "GCC Version <5.3.0 detected, using -O0 flag... You should upgrade!" - export CFLAGS="${CFLAGS/-O2/} -O0" - export CXXFLAGS="${CXXFLAGS/-O2/} -O0" - fi - # These additional CPPFLAGS solve FS#27662 and FS#34195 export CPPFLAGS="${CPPFLAGS/-D_FORTIFY_SOURCE=2/} -D_FORTIFY_SOURCE=0" diff --git a/nine-1.8rc2.patch b/nine-1.8.patch index 8dbfe8614cb3..2f001ac3e5fe 100644 --- a/nine-1.8rc2.patch +++ b/nine-1.8.patch @@ -1,5 +1,5 @@ diff --git a/configure b/configure -index 5ecd109..be2483f 100755 +index f52c979..ce20dab 100755 --- a/configure +++ b/configure @@ -681,6 +681,8 @@ XSLT_LIBS @@ -734,7 +734,7 @@ index 5ecd109..be2483f 100755 wine_fn_config_dll d3dcompiler_34 enable_d3dcompiler_34 wine_fn_config_dll d3dcompiler_35 enable_d3dcompiler_35 diff --git a/configure.ac b/configure.ac -index c548352..428e9ba 100644 +index aa829be..5b18b0a 100644 --- a/configure.ac +++ b/configure.ac @@ -67,6 +67,8 @@ AC_ARG_WITH(openal, AS_HELP_STRING([--without-openal],[do not use OpenAL]), @@ -809,34 +809,6 @@ index c548352..428e9ba 100644 WINE_CONFIG_DLL(d3dcompiler_33) WINE_CONFIG_DLL(d3dcompiler_34) WINE_CONFIG_DLL(d3dcompiler_35) -diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c -index 8b98e4a..d6b2382 100644 ---- a/dlls/advapi32/tests/security.c -+++ b/dlls/advapi32/tests/security.c -@@ -3448,7 +3448,6 @@ static void test_CreateDirectoryA(void) - ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); - bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); - ok(bret, "GetAclInformation failed\n"); -- todo_wine - ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", - acl_size.AceCount); - LocalFree(pSD); -@@ -3507,6 +3506,7 @@ static void test_CreateDirectoryA(void) - ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); - bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); - ok(bret, "GetAclInformation failed\n"); -+ todo_wine - ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", - acl_size.AceCount); - LocalFree(pSD); -@@ -3593,7 +3593,6 @@ static void test_CreateDirectoryA(void) - ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error); - bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); - ok(bret, "GetAclInformation failed\n"); -- todo_wine - ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", - acl_size.AceCount); - LocalFree(pSD); diff --git a/dlls/d3d9/Makefile.in b/dlls/d3d9/Makefile.in index 1c05f5a..dc06d68 100644 --- a/dlls/d3d9/Makefile.in @@ -849,421 +821,6 @@ index 1c05f5a..dc06d68 100644 C_SRCS = \ buffer.c \ -diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c -index 151db41..5314915 100644 ---- a/dlls/d3d9/tests/d3d9ex.c -+++ b/dlls/d3d9/tests/d3d9ex.c -@@ -1410,6 +1410,7 @@ static void test_lost_device(void) - HRESULT hr; - BOOL ret; - struct device_desc desc; -+ IDirect3DSwapChain9 *swapchain; - - window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW, - 0, 0, 640, 480, NULL, NULL, NULL, NULL); -@@ -1434,6 +1435,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); - ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - ret = SetForegroundWindow(GetDesktopWindow()); - ok(ret, "Failed to set foreground window.\n"); - hr = IDirect3DDevice9Ex_TestCooperativeLevel(device); -@@ -1447,6 +1454,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - ret = SetForegroundWindow(window); - ok(ret, "Failed to set foreground window.\n"); - hr = IDirect3DDevice9Ex_TestCooperativeLevel(device); -@@ -1460,6 +1473,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); - ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - desc.width = 1024; - desc.height = 768; - hr = reset_device(device, &desc); -@@ -1489,6 +1508,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); - todo_wine ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - hr = reset_device(device, &desc); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - hr = IDirect3DDevice9Ex_TestCooperativeLevel(device); -@@ -1502,6 +1527,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - ret = SetForegroundWindow(GetDesktopWindow()); - ok(ret, "Failed to set foreground window.\n"); - hr = IDirect3DDevice9Ex_TestCooperativeLevel(device); -diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c -index 5579826..2cdf584 100644 ---- a/dlls/d3d9/tests/device.c -+++ b/dlls/d3d9/tests/device.c -@@ -8229,10 +8229,10 @@ done: - - static void test_vidmem_accounting(void) - { -- IDirect3DDevice9 *device; -+ IDirect3DDevice9 *device, *device2; - IDirect3D9 *d3d9; - ULONG refcount; -- HWND window; -+ HWND window, window2; - HRESULT hr = D3D_OK; - IDirect3DTexture9 *textures[20]; - unsigned int i; -@@ -8240,6 +8240,8 @@ static void test_vidmem_accounting(void) - - window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW, - 0, 0, 640, 480, 0, 0, 0, 0); -+ window2 = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW, -+ 0, 0, 640, 480, 0, 0, 0, 0); - d3d9 = Direct3DCreate9(D3D_SDK_VERSION); - ok(!!d3d9, "Failed to create a D3D object.\n"); - if (!(device = create_device(d3d9, window, NULL))) -@@ -8274,6 +8276,43 @@ static void test_vidmem_accounting(void) - IDirect3DTexture9_Release(textures[i]); - } - -+ /* Multi-device testing */ -+ if (!(device2 = create_device(d3d9, window2, NULL))) -+ { -+ skip("Failed to create a D3D device, skipping tests.\n"); -+ refcount = IDirect3DDevice9_Release(device); -+ ok(!refcount, "Device has %u references left.\n", refcount); -+ IDirect3D9_Release(d3d9); -+ DestroyWindow(window2); -+ DestroyWindow(window); -+ return; -+ } -+ -+ vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device); -+ memset(textures, 0, sizeof(textures)); -+ for (i = 0; (i < sizeof(textures) / sizeof(*textures)) && SUCCEEDED(hr); i++) -+ { -+ hr = IDirect3DDevice9_CreateTexture(device2, 1024, 1024, 1, D3DUSAGE_RENDERTARGET, -+ D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL); -+ /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory -+ * E_FAIL is returned on address space or system memory exhaustion */ -+ ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY, -+ "Failed to create texture, hr %#x.\n", hr); -+ } -+ vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device); -+ -+ /* Windows 7 uses device private counters */ -+ ok(vidmem_start > vidmem_end || broken(vidmem_start == vidmem_end), "Expected available texture memory to decrease during texture creation.\n"); -+ diff = vidmem_start - vidmem_end; -+ ok(diff > 1024 * 1024 * 2 * i || broken(diff == 0), "Expected a video memory difference of at least %u MB, got %u MB.\n", -+ 2 * i, diff / 1024 / 1024); -+ -+ for (i = 0; i < sizeof(textures) / sizeof(*textures); i++) -+ { -+ if (textures[i]) -+ IDirect3DTexture9_Release(textures[i]); -+ } -+ - refcount = IDirect3DDevice9_Release(device); - ok(!refcount, "Device has %u references left.\n", refcount); - IDirect3D9_Release(d3d9); -@@ -9999,6 +10038,7 @@ static void test_lost_device(void) - HWND window; - HRESULT hr; - BOOL ret; -+ IDirect3DSwapChain9 *swapchain; - - window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW, - 0, 0, 640, 480, NULL, NULL, NULL, NULL); -@@ -10026,6 +10066,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - ret = ShowWindow(window, SW_RESTORE); - ok(ret, "Failed to restore window.\n"); - ret = SetForegroundWindow(window); -@@ -10035,6 +10081,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - hr = reset_device(device, &device_desc); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - hr = IDirect3DDevice9_TestCooperativeLevel(device); -@@ -10042,6 +10094,12 @@ static void test_lost_device(void) - hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - -+ hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain); -+ ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr); -+ hr = IDirect3DSwapChain9_Present(swapchain, NULL, NULL, NULL, NULL, 0); -+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); -+ IDirect3DSwapChain9_Release(swapchain); -+ - device_desc.flags = 0; - hr = reset_device(device, &device_desc); - ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); -diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c -index 6fe9e56..99adde0 100644 ---- a/dlls/d3d9/tests/visual.c -+++ b/dlls/d3d9/tests/visual.c -@@ -8539,6 +8539,167 @@ done: - DestroyWindow(window); - } - -+static void test_blend_invalid_arg(void) -+{ -+ IDirect3DSurface9 *backbuffer, *offscreen; -+ IDirect3DTexture9 *offscreenTexture; -+ IDirect3DDevice9 *device; -+ IDirect3D9 *d3d; -+ D3DCOLOR color; -+ ULONG refcount; -+ HWND window; -+ HRESULT hr; -+ DWORD rs; -+ -+ static const struct -+ { -+ struct vec3 position; -+ DWORD diffuse; -+ } -+ quad1[] = -+ { -+ {{-1.0f, -1.0f, 0.1f}, 0x4000ff00}, -+ {{-1.0f, 0.0f, 0.1f}, 0x4000ff00}, -+ {{ 0.0f, -1.0f, 0.1f}, 0x4000ff00}, -+ {{ 0.0f, 0.0f, 0.1f}, 0x4000ff00}, -+ }, -+ quad2[] = -+ { -+ {{ 0.0f, 0.0f, 0.1f}, 0x4000ff00}, -+ {{ 0.0f, 1.0f, 0.1f}, 0x4000ff00}, -+ {{ 1.0f, 0.0f, 0.1f}, 0x4000ff00}, -+ {{ 1.0f, 1.0f, 0.1f}, 0x4000ff00}, -+ }, -+ quad3[] = -+ { -+ {{-1.0f, 0.0f, 0.1f}, 0xc00000ff}, -+ {{-1.0f, 1.0f, 0.1f}, 0xc00000ff}, -+ {{ 0.0f, 0.0f, 0.1f}, 0xc00000ff}, -+ {{ 0.0f, 1.0f, 0.1f}, 0xc00000ff}, -+ }, -+ quad4[] = -+ { -+ {{ 0.0f, -1.0f, 0.1f}, 0xc00000ff}, -+ {{ 0.0f, 0.0f, 0.1f}, 0xc00000ff}, -+ {{ 1.0f, -1.0f, 0.1f}, 0xc00000ff}, -+ {{ 1.0f, 0.0f, 0.1f}, 0xc00000ff}, -+ }; -+ -+ window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, -+ 0, 0, 640, 480, NULL, NULL, NULL, NULL); -+ d3d = Direct3DCreate9(D3D_SDK_VERSION); -+ ok(!!d3d, "Failed to create a D3D object.\n"); -+ if (!(device = create_device(d3d, window, window, TRUE))) -+ { -+ skip("Failed to create a D3D device, skipping tests.\n"); -+ goto done; -+ } -+ /* Clear the render target with alpha = 0.5 */ -+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x80ff0000, 1.0f, 0); -+ ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr); -+ -+ hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, -+ D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL); -+ ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); -+ -+ hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); -+ ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr); -+ -+ hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen); -+ ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr); -+ -+ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); -+ ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr); -+ -+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); -+ ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr); -+ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); -+ ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr); -+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); -+ ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr); -+ hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); -+ ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr); -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); -+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr); -+ -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE); -+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr); -+ hr = IDirect3DDevice9_BeginScene(device); -+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); -+ -+ /* draw quad to test default renderstate -+ * expect D3DRS_SRCBLEND == D3DBLEND_ONE -+ * expect D3DRS_DESTBLEND == D3DBLEND_ZERO */ -+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0])); -+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); -+ -+ /* set invalid value and expect D3DBLEND_ZERO instead */ -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, 0); -+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); -+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_SRCBLEND, &rs); -+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); -+ ok(rs == 0, "Unexpected renderstate %#x.\n", rs); -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); -+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); -+ -+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0])); -+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); -+ /* set non default valid values */ -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); -+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); -+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_SRCBLEND, &rs); -+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); -+ ok(rs == D3DBLEND_SRCALPHA, "Unexpected renderstate %#x.\n", rs); -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); -+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); -+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_DESTBLEND, &rs); -+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); -+ ok(rs == D3DBLEND_INVSRCALPHA, "Failed to get render state, hr %#x.\n", hr); -+ -+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0])); -+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); -+ -+ /* set invalid value and expect D3DBLEND_ZERO instead */ -+ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, 200); -+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); -+ hr = IDirect3DDevice9_GetRenderState(device, D3DRS_DESTBLEND, &rs); -+ ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); -+ ok(rs == 200, "Failed to get render state, hr %#x.\n", hr); -+ -+ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0])); -+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); -+ -+ hr = IDirect3DDevice9_EndScene(device); -+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); -+ -+ color = getPixelColor(device, 160, 360); -+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1), -+ "D3DRS_SRCBLEND ONE returned color %08x, expected 0x0000FF00\n", color); -+ -+ color = getPixelColor(device, 480, 120); -+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x00, 0x00), 1), -+ "invalid D3DRS_SRCBLEND returned color %08x, expected 0x00bf0000\n", color); -+ -+ color = getPixelColor(device, 160, 120); -+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x3f, 0x00, 0xC0), 1), -+ "D3DRS_SRCBLEND SRCALPHA returned color %08x, expected 0x003f00C0\n", color); -+ -+ color = getPixelColor(device, 480, 360); -+ ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xC0), 1), -+ "invalid D3DRS_DESTBLEND returned color %08x, expected 0x000000C0\n", color); -+ -+ IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); -+ -+ IDirect3DSurface9_Release(backbuffer); -+ IDirect3DTexture9_Release(offscreenTexture); -+ IDirect3DSurface9_Release(offscreen); -+ refcount = IDirect3DDevice9_Release(device); -+ ok(!refcount, "Device has %u references left.\n", refcount); -+done: -+ IDirect3D9_Release(d3d); -+ DestroyWindow(window); -+} -+ - static void fixed_function_decl_test(void) - { - IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL; -@@ -12738,6 +12899,9 @@ static void alphatest_test(void) - } - testdata[] = - { -+ /* test invalid values, D3DCMP_NEVER for values less than D3DCMP_NEVER, -+ * D3DCMP_ALWAYS for values greater than D3DCMP_ALWAYS */ -+ {D3DCMP_NEVER-1, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED}, - {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED}, - {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED}, - {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED}, -@@ -12746,6 +12910,10 @@ static void alphatest_test(void) - {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED}, - {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED}, - {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED}, -+ {D3DCMP_ALWAYS+1, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED}, -+ {D3DCMP_ALWAYS+2, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED}, -+ {D3DCMP_ALWAYS+3, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED}, -+ {0xdeadbeef, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED}, - }; - static const struct - { -@@ -18095,6 +18263,27 @@ static void test_negative_fixedfunction_fog(void) - D3DFOG_LINEAR, D3DFOG_NONE, 0x0000ff00, 0x0000ff00, 0x0000ff00}, - {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, - D3DFOG_EXP, D3DFOG_NONE, 0x009b6400, 0x009b6400, 0x009b6400}, -+ /* test invalid values, expect a modulo 4 on samplerstate */ -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+1, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+2, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+3, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+4, D3DFOG_NONE, 0x007f7f00, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+5, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+6, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+7, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+8, D3DFOG_NONE, 0x007f7f00, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+9, D3DFOG_NONE, 0x0000ff00, 0x009b6400, 0x009b6400}, -+ {D3DFVF_XYZ, quad, sizeof(*quad), &zero, { 0.0f}, {1.0f}, -+ D3DFOG_LINEAR+10, D3DFOG_NONE, 0x00c73800, 0x009b6400, 0x009b6400}, - }; - D3DCAPS9 caps; - diff --git a/dlls/d3d9-nine/Makefile.in b/dlls/d3d9-nine/Makefile.in new file mode 100644 index 0000000..a761cd7 @@ -5411,7 +4968,7 @@ index 81a4e24..96bc9a4 100644 break; } diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc -index a9c62ae..cbde6aa 100644 +index e2b35a2..7b444d0 100644 --- a/programs/winecfg/winecfg.rc +++ b/programs/winecfg/winecfg.rc @@ -320,6 +320,8 @@ BEGIN diff --git a/sni_support.patch b/sni_support.patch deleted file mode 100644 index ff801058af2d..000000000000 --- a/sni_support.patch +++ /dev/null @@ -1,2010 +0,0 @@ -@@ -, +, @@ ---- - dlls/winex11.drv/Makefile.in | 3 +- - dlls/winex11.drv/systray.c | 56 +- - dlls/winex11.drv/systray.h | 77 ++ - dlls/winex11.drv/systray_dbus.c | 1814 +++++++++++++++++++++++++++++++++++++++ - 4 files changed, 1921 insertions(+), 29 deletions(-) - create mode 100644 dlls/winex11.drv/systray.h - create mode 100644 dlls/winex11.drv/systray_dbus.c ---- a/dlls/winex11.drv/Makefile.in -+++ a/dlls/winex11.drv/Makefile.in -@@ -1,7 +1,7 @@ - MODULE = winex11.drv - IMPORTS = uuid user32 gdi32 advapi32 - DELAYIMPORTS = comctl32 ole32 shell32 imm32 --EXTRAINCL = $(X_CFLAGS) -+EXTRAINCL = $(X_CFLAGS) $(DBUS_CFLAGS) - EXTRALIBS = $(X_LIBS) $(X_EXTRA_LIBS) - - C_SRCS = \ -@@ -20,6 +20,7 @@ C_SRCS = \ - pen.c \ - settings.c \ - systray.c \ -+ systray_dbus.c \ - window.c \ - wintab.c \ - x11drv_main.c \ ---- a/dlls/winex11.drv/systray.c -+++ a/dlls/winex11.drv/systray.c -@@ -44,28 +44,10 @@ - #include "wine/list.h" - #include "wine/debug.h" - --WINE_DEFAULT_DEBUG_CHANNEL(systray); -+#include "systray.h" - --/* an individual systray icon */ --struct tray_icon --{ -- struct list entry; -- HICON image; /* the image to render */ -- HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ -- HWND window; /* the adaptor window */ -- BOOL layered; /* whether we are using a layered window */ -- HWND tooltip; /* Icon tooltip */ -- UINT state; /* state flags */ -- UINT id; /* the unique id given by the app */ -- UINT callback_message; -- int display; /* display index, or -1 if hidden */ -- WCHAR tiptext[128]; /* tooltip text */ -- WCHAR info_text[256]; /* info balloon text */ -- WCHAR info_title[64]; /* info balloon title */ -- UINT info_flags; /* flags for info balloon */ -- UINT info_timeout; /* timeout for info balloon */ -- HICON info_icon; /* info balloon icon */ --}; -+ -+WINE_DEFAULT_DEBUG_CHANNEL(systray); - - static struct list icon_list = LIST_INIT( icon_list ); - -@@ -88,9 +70,6 @@ Atom systray_atom = 0; - #define BALLOON_CREATE_TIMER 1 - #define BALLOON_SHOW_TIMER 2 - --#define BALLOON_CREATE_TIMEOUT 2000 --#define BALLOON_SHOW_MIN_TIMEOUT 10000 --#define BALLOON_SHOW_MAX_TIMEOUT 30000 - - static struct tray_icon *balloon_icon; - static HWND balloon_window; -@@ -825,14 +804,35 @@ int CDECL wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data ) - switch (msg) - { - case NIM_ADD: -- if (!init_systray()) return -1; /* fall back to default handling */ -- ret = add_icon( data ); -+ if (can_use_dbus_sni_systray()) -+ { -+ ret = add_sni_icon( data ); -+ } -+ else -+ { -+ if (!init_systray()) return -1; /* fall back to default handling */ -+ ret = add_icon( data ); -+ } - break; - case NIM_DELETE: -- if ((icon = get_icon( data->hWnd, data->uID ))) ret = delete_icon( icon ); -+ if (can_use_dbus_sni_systray()) -+ { -+ ret = delete_sni_icon( data ); -+ } -+ else -+ { -+ if ((icon = get_icon( data->hWnd, data->uID ))) ret = delete_icon( icon ); -+ } - break; - case NIM_MODIFY: -- if ((icon = get_icon( data->hWnd, data->uID ))) ret = modify_icon( icon, data ); -+ if (can_use_dbus_sni_systray()) -+ { -+ ret = modify_sni_icon( data ); -+ } -+ else -+ { -+ if ((icon = get_icon( data->hWnd, data->uID ))) ret = modify_icon( icon, data ); -+ } - break; - case 0xdead: /* Wine extension: owner window has died */ - cleanup_icons( data->hWnd ); ---- a/dlls/winex11.drv/systray.h -+++ a/dlls/winex11.drv/systray.h -@@ -0,0 +1,77 @@ -+/* -+ * X11 driver systray-specific definitions -+ * -+ * Copyright (C) 2004 Mike Hearn, for CodeWeavers -+ * Copyright (C) 2005 Robert Shearman -+ * Copyright (C) 2008 Alexandre Julliard -+ * Copyright (C) 2015 Alexey Minnekhanov -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#ifndef __WINE_SYSTRAY_H -+#define __WINE_SYSTRAY_H -+ -+ -+#include "windef.h" -+#include "wine/list.h" -+ -+ -+/* This file contains declarations shared between systray.c and -+ * systray_dbus.c (to avoid modification of x11drv.h) */ -+ -+ -+#define BALLOON_CREATE_TIMEOUT 2000 -+#define BALLOON_SHOW_MIN_TIMEOUT 10000 -+#define BALLOON_SHOW_MAX_TIMEOUT 30000 -+ -+ -+/* an individual systray icon */ -+struct tray_icon -+{ -+ struct list entry; -+ HICON image; /* the image to render */ -+ HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ -+ HWND window; /* the adaptor window */ -+ BOOL layered; /* whether we are using a layered window */ -+ HWND tooltip; /* Icon tooltip */ -+ UINT state; /* state flags */ -+ UINT id; /* the unique id given by the app */ -+ UINT callback_message; -+ int display; /* display index, or -1 if hidden */ -+ WCHAR tiptext[128]; /* tooltip text */ -+ WCHAR info_text[256]; /* info balloon text */ -+ WCHAR info_title[64]; /* info balloon title */ -+ UINT info_flags; /* flags for info balloon */ -+ UINT info_timeout; /* timeout for info balloon */ -+ HICON info_icon; /* info balloon icon */ -+ /* DBus SNI specific members */ -+ char dbus_name[64]; /* name of dbus object */ -+ char sni_title[64]; /* title of status notifier */ -+ /* For SNI we must keep icon image this way, as an array of bitmap bits */ -+ int icon_w; /* tray icon width */ -+ int icon_h; /* tray icon height */ -+ unsigned char *icon_data; /* tray icon pixels */ -+}; -+ -+ -+extern BOOL can_use_dbus_sni_systray(void) DECLSPEC_HIDDEN; -+ -+extern BOOL add_sni_icon(NOTIFYICONDATAW *nid) DECLSPEC_HIDDEN; -+extern BOOL modify_sni_icon(NOTIFYICONDATAW *nid) DECLSPEC_HIDDEN; -+extern BOOL delete_sni_icon(NOTIFYICONDATAW *nid) DECLSPEC_HIDDEN; -+ -+ -+#endif /* __WINE_SYSTRAY_H */ ---- a/dlls/winex11.drv/systray_dbus.c -+++ a/dlls/winex11.drv/systray_dbus.c -@@ -0,0 +1,1814 @@ -+/* -+ * DBus StatusNotifierItem system tray management, -+ * -+ * Copyright (C) 2004 Mike Hearn, for CodeWeavers -+ * Copyright (C) 2005 Robert Shearman -+ * Copyright (C) 2008 Alexandre Julliard -+ * Copyright (C) 2015 Alexey Minnekhanov -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+/* -+ * This file holds all functionality to implement all DBus-related -+ * operations to implement StatusNotifierItem specification -+ * (see http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ ) -+ * Keep it separated from systray.c if possible. -+ * Functions in this module will be called from systray.c, -+ * from wine_notify_icon(). Module public module interface: -+ * -+ * - BOOL can_use_dbus_sni_systray(void) - checks if SNI systray can be used -+ * in this system. -+ * - BOOL add_sni_icon( NOTIFYICONDATAW* ) - add new systray icon -+ * - BOOL modify_sni_icon( NOTIFYICONDATAW* ) - all edit icon operations -+ * - BOOL delete_sni_icon( NOTIFYICONDATAW* ) - remove status notifier item -+ */ -+ -+#include "config.h" -+#include "wine/port.h" -+ -+#include <assert.h> -+#include <stdarg.h> -+#include <stdlib.h> -+#include <stdio.h> -+#ifdef HAVE_UNISTD_H -+# include <unistd.h> -+#endif -+ -+#ifdef SONAME_LIBDBUS_1 -+# include <dbus/dbus.h> -+#endif -+ -+#define NONAMELESSUNION -+#include "windef.h" -+#include "winbase.h" -+#include "wingdi.h" -+#include "winuser.h" -+#include "shellapi.h" -+ -+#include "wine/debug.h" -+#include "wine/library.h" -+#include "wine/list.h" -+#include "wine/unicode.h" -+ -+#include "systray.h" -+#include "x11drv.h" -+ -+ -+WINE_DEFAULT_DEBUG_CHANNEL(systray); -+ -+ -+#ifdef SONAME_LIBDBUS_1 -+ -+/* Similar code to load DBus is used in dlls/mountmgr.sys/dbus.c */ -+ -+#define DBUS_FUNCS \ -+ DO_FUNC(dbus_bus_get); \ -+ DO_FUNC(dbus_bus_get_unique_name); \ -+ DO_FUNC(dbus_bus_name_has_owner); \ -+ DO_FUNC(dbus_bus_release_name); \ -+ DO_FUNC(dbus_bus_request_name); \ -+ DO_FUNC(dbus_connection_read_write_dispatch); \ -+ DO_FUNC(dbus_connection_send); \ -+ DO_FUNC(dbus_connection_send_with_reply_and_block); \ -+ DO_FUNC(dbus_connection_set_exit_on_disconnect); \ -+ DO_FUNC(dbus_connection_try_register_fallback); \ -+ DO_FUNC(dbus_connection_unref); \ -+ DO_FUNC(dbus_connection_unregister_object_path); \ -+ DO_FUNC(dbus_error_free); \ -+ DO_FUNC(dbus_error_init); \ -+ DO_FUNC(dbus_message_append_args); \ -+ DO_FUNC(dbus_message_get_args); \ -+ DO_FUNC(dbus_message_get_destination); \ -+ DO_FUNC(dbus_message_get_interface); \ -+ DO_FUNC(dbus_message_get_member); \ -+ DO_FUNC(dbus_message_get_path); \ -+ DO_FUNC(dbus_message_get_signature); \ -+ DO_FUNC(dbus_message_is_method_call); \ -+ DO_FUNC(dbus_message_iter_append_basic); \ -+ DO_FUNC(dbus_message_iter_close_container); \ -+ DO_FUNC(dbus_message_iter_get_arg_type); \ -+ DO_FUNC(dbus_message_iter_get_basic); \ -+ DO_FUNC(dbus_message_iter_init); \ -+ DO_FUNC(dbus_message_iter_init_append); \ -+ DO_FUNC(dbus_message_iter_next); \ -+ DO_FUNC(dbus_message_iter_open_container); \ -+ DO_FUNC(dbus_message_iter_recurse); \ -+ DO_FUNC(dbus_message_new_error); \ -+ DO_FUNC(dbus_message_new_method_call); \ -+ DO_FUNC(dbus_message_new_method_return); \ -+ DO_FUNC(dbus_message_new_signal); \ -+ DO_FUNC(dbus_message_unref); -+ -+/* libdbus function pointers */ -+#define DO_FUNC(f) static typeof(f) * p_##f -+DBUS_FUNCS; -+#undef DO_FUNC -+ -+ -+/* DBus connection handle */ -+static DBusConnection *d_connection = NULL; -+ -+/* structure to keep all managed icons */ -+static struct list icon_list = LIST_INIT( icon_list ); -+/* we need our own list, different from that one in systray.c -+ * just to make as little modifications to existing code as possible */ -+static int g_icons_count = 0; -+ -+/* global that indicates DBus message loop thread state */ -+static BOOL g_dbus_thread_running = FALSE; -+ -+/* Critical section guarding DBus connection object */ -+CRITICAL_SECTION g_dconn_cs; -+ -+/* local forwards */ -+static BOOL delete_icon(struct tray_icon *icon); -+ -+ -+/* DBus introspection XMLs definitions */ -+/* For documentation of DBus introspection XML format, -+ * see http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format */ -+ -+/* root object XML */ -+static const char *g_dbus_introspect_xml_root_with_SNI = "" -+"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"" -+" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" -+"<node name=\"/\">\n" -+" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" -+" <method name=\"Introspect\">\n" -+" <arg name=\"xml_data\" type=\"s\" direction=\"out\"/>\n" -+" </method>\n" -+" </interface>\n" -+" <interface name=\"org.freedesktop.DBus.Properties\">\n" -+" <method name=\"Get\">\n" -+" <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" -+" <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" -+" <arg name=\"value\" type=\"v\" direction=\"out\"/>\n" -+" </method>\n" -+" <method name=\"Set\">\n" -+" <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" -+" <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" -+" <arg name=\"value\" type=\"v\" direction=\"in\"/>\n" -+" </method>\n" -+" <method name=\"GetAll\">\n" -+" <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" -+" <arg name=\"props\" type=\"{sv}\" direction=\"out\"/>\n" -+" </method>\n" -+" </interface>\n" -+" <node name=\"StatusNotifierItem\"/>\n" -+"</node>"; -+ -+/* /StatusNotifierItem XML */ -+static const char *g_dbus_introspect_xml_SNI = "\ -+<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\ -+ \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\ -+<node name=\"/StatusNotifierItem\">\ -+ <interface name=\"org.freedesktop.DBus.Introspectable\">\ -+ <method name=\"Introspect\">\ -+ <arg name=\"xml_data\" type=\"s\" direction=\"out\"/>\ -+ </method>\ -+ </interface>\ -+ <interface name=\"org.freedesktop.DBus.Properties\">\ -+ <method name=\"Get\">\ -+ <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\ -+ <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\ -+ <arg name=\"value\" type=\"v\" direction=\"out\"/>\ -+ </method>\ -+ <method name=\"Set\">\ -+ <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\ -+ <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\ -+ <arg name=\"value\" type=\"v\" direction=\"in\"/>\ -+ </method>\ -+ <method name=\"GetAll\">\ -+ <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\ -+ <arg name=\"props\" type=\"{sv}\" direction=\"out\"/>\ -+ </method>\ -+ </interface>\ -+ <interface name=\"org.kde.StatusNotifierItem\">\ -+ <property name=\"Category\" type=\"s\" access=\"read\"/>\ -+ <property name=\"Id\" type=\"s\" access=\"read\"/>\ -+ <property name=\"Title\" type=\"s\" access=\"read\"/>\ -+ <property name=\"Status\" type=\"s\" access=\"read\"/>\ -+ <property name=\"WindowId\" type=\"u\" access=\"read\"/>\ -+ <property name=\"IconName\" type=\"s\" access=\"read\"/>\ -+ <property name=\"IconPixmap\" type=\"a(iiay)\" access=\"read\"/>\ -+ <property name=\"OverlayIconName\" type=\"s\" access=\"read\"/>\ -+ <property name=\"OverlayIconPixmap\" type=\"a(iiay)\" access=\"read\"/>\ -+ <property name=\"AttentionIconName\" type=\"s\" access=\"read\"/>\ -+ <property name=\"AttentionIconPixmap\" type=\"a(iiay)\" access=\"read\"/>\ -+ <property name=\"AttentionMovieName\" type=\"s\" access=\"read\"/>\ -+ <property name=\"ToolTip\" type=\"(sa(iiay)ss)\" access=\"read\"/>\ -+ <method name=\"ContextMenu\">\ -+ <arg name=\"x\" type=\"i\" direction=\"in\"/>\ -+ <arg name=\"y\" type=\"i\" direction=\"in\"/>\ -+ </method>\ -+ <method name=\"Activate\">\ -+ <arg name=\"x\" type=\"i\" direction=\"in\"/>\ -+ <arg name=\"y\" type=\"i\" direction=\"in\"/>\ -+ </method>\ -+ <method name=\"SecondaryActivate\">\ -+ <arg name=\"x\" type=\"i\" direction=\"in\"/>\ -+ <arg name=\"y\" type=\"i\" direction=\"in\"/>\ -+ </method>\ -+ <method name=\"Scroll\">\ -+ <arg name=\"delta\" type=\"i\" direction=\"in\"/>\ -+ <arg name=\"orientation\" type=\"s\" direction=\"in\"/>\ -+ </method>\ -+ <signal name=\"NewTitle\"></signal>\ -+ <signal name=\"NewIcon\"></signal>\ -+ <signal name=\"NewAttentionIcon\"></signal>\ -+ <signal name=\"NewOverlayIcon\"></signal>\ -+ <signal name=\"NewToolTip\"></signal>\ -+ <signal name=\"NewStatus\">\ -+ <arg name=\"status\" type=\"s\"/>\ -+ </signal>\ -+ </interface>\ -+</node>"; -+ -+ -+/************************************************************** -+ icon_list management functions -+***************************************************************/ -+ -+/* Retrieves icon record by owner window and ID */ -+static struct tray_icon *get_icon_from_list(HWND owner, UINT id) -+{ -+ struct tray_icon *this; -+ -+ LIST_FOR_EACH_ENTRY( this, &icon_list, struct tray_icon, entry ) -+ if ((this->id == id) && (this->owner == owner)) return this; -+ return NULL; -+} -+ -+ -+/* Retrieves icon record by DBus name */ -+static struct tray_icon *get_icon_from_list_by_dname(const char *dname) -+{ -+ struct tray_icon *this; -+ -+ LIST_FOR_EACH_ENTRY( this, &icon_list, struct tray_icon, entry ) -+ if (strcmp(this->dbus_name, dname) == 0) return this; -+ return NULL; -+} -+ -+ -+/* Allocates memory and adds a new icon to the list */ -+static struct tray_icon *add_new_icon_to_list(void) -+{ -+ struct tray_icon *icon; -+ -+ /* allocate memory */ -+ if (!(icon = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*icon)))) -+ { -+ ERR("out of memory\n"); -+ return FALSE; -+ } -+ ZeroMemory(icon, sizeof(struct tray_icon)); -+ -+ /* add to list */ -+ list_add_tail(&icon_list, &icon->entry); -+ g_icons_count++; -+ return icon; -+} -+ -+ -+/* Removes icons from list and frees its memory */ -+static void delete_icon_from_list(struct tray_icon *icon) -+{ -+ if (!icon) return; -+ list_remove( &icon->entry ); -+ g_icons_count--; -+ HeapFree( GetProcessHeap(), 0, icon ); -+} -+ -+ -+ -+/************************************************************** -+ DBus initialization functions -+***************************************************************/ -+ -+static BOOL load_dbus_functions(void) -+{ -+ void *handle; -+ char error[128]; -+ -+ if (!(handle = wine_dlopen(SONAME_LIBDBUS_1, RTLD_NOW, error, sizeof(error)))) -+ goto failed; -+ -+#define DO_FUNC(f) if (!(p_##f = wine_dlsym( handle, #f, error, sizeof(error) ))) goto failed -+ DBUS_FUNCS; -+#undef DO_FUNC -+ return TRUE; -+ -+failed: -+ WARN( "failed to load DBus support: %s\n", error ); -+ return FALSE; -+} -+ -+ -+static BOOL initialize_dbus(void) -+{ -+ static BOOL init_done = FALSE; -+ if (init_done) return TRUE; -+ -+ if (load_dbus_functions()) -+ { -+ InitializeCriticalSection( &g_dconn_cs ); -+ -+ init_done = TRUE; -+ d_connection = NULL; -+ } -+ -+ TRACE( "Initialize DBUS OK\n" ); -+ return TRUE; -+} -+ -+ -+/************************************************************* -+ * DBus reply helper functions -+**************************************************************/ -+ -+ -+/* Locks connection lock, sends message and unlocks the lock. -+ * Safe to use with message loop thread running. */ -+static dbus_bool_t dbus_send_safe(DBusMessage *msg) -+{ -+ dbus_bool_t resb; -+ -+ if (!d_connection) return FALSE; -+ if (!msg) return FALSE; -+ -+ EnterCriticalSection( &g_dconn_cs ); -+ resb = p_dbus_connection_send(d_connection, msg, NULL); -+ LeaveCriticalSection( &g_dconn_cs ); -+ -+ if (resb == FALSE) -+ { -+ WARN("dbus_connection_send() failed!\n"); -+ } -+ -+ return resb; -+} -+ -+ -+/* this creates response message with simlple string value */ -+static DBusMessage *create_introspect_reply( -+ DBusMessage *msg, -+ const char *reply_xml) -+{ -+ dbus_bool_t retb; -+ DBusMessage *reply; -+ -+ reply = p_dbus_message_new_method_return(msg); -+ if( reply ) -+ { -+ retb = p_dbus_message_append_args(reply, -+ DBUS_TYPE_STRING, &reply_xml, -+ DBUS_TYPE_INVALID); -+ if( retb == FALSE ) -+ { -+ p_dbus_message_unref(reply); -+ reply = NULL; -+ } -+ } -+ return reply; -+} -+ -+ -+/* this should reply DBUS_VARIANT type with internal STRING value */ -+static DBusMessage *create_reply_propget_s(DBusMessage *msg, const char *s) -+{ -+ DBusMessage *reply; -+ DBusMessageIter iter, sub_iter; -+ -+ reply = p_dbus_message_new_method_return(msg); -+ if( !reply ) return FALSE; -+ -+ /* we can send VARIANT only with iterator */ -+ p_dbus_message_iter_init_append(reply, &iter); -+ p_dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub_iter); -+ p_dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, &s); -+ p_dbus_message_iter_close_container(&iter, &sub_iter); -+ return reply; -+} -+ -+ -+/* this should reply DBUS_VARIANT type with internal UINT32 value */ -+static DBusMessage *create_reply_propget_u(DBusMessage *msg, dbus_uint32_t value) -+{ -+ DBusMessage *reply; -+ DBusMessageIter iter, sub_iter; -+ -+ reply = p_dbus_message_new_method_return(msg); -+ if( !reply ) return FALSE; -+ -+ /* we can send VARIANT only with iterator */ -+ p_dbus_message_iter_init_append(reply, &iter); -+ p_dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "u", &sub_iter); -+ p_dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_UINT32, &value); -+ p_dbus_message_iter_close_container(&iter, &sub_iter); -+ return reply; -+} -+ -+ -+static DBusMessage *create_reply_propget_pixmap( -+ DBusMessage *msg, -+ int icon_width, -+ int icon_height, -+ const unsigned char *img_data ) -+{ -+ DBusMessage *reply; -+ DBusMessageIter iter, v_iter, a_iter, st_iter, pixels_arr_iter; -+ int num_pixels, i; -+ unsigned char pixel_byte; -+ -+ reply = p_dbus_message_new_method_return(msg); -+ if( !reply ) return FALSE; -+ -+ /* variant, containing array: a(iiay) -+ * array of structures: (int, int, bytearray): width, height, -+ * bits data in ARGB32 format (network byte order) -+ * Reply can contain array of pixmaps in different sizes, but we send only one */ -+ p_dbus_message_iter_init_append(reply, &iter); -+ p_dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "a(iiay)", &v_iter); -+ p_dbus_message_iter_open_container(&v_iter, DBUS_TYPE_ARRAY, "(iiay)", &a_iter); -+ if( (icon_height > 0) && (icon_width > 0) && (img_data)) { -+ /* open structure container */ -+ p_dbus_message_iter_open_container(&a_iter, DBUS_TYPE_STRUCT, NULL, &st_iter); -+ /* write icon width, height */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_INT32, &icon_width); -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_INT32, &icon_height); -+ /* write icon bytes data as array */ -+ /* open array */ -+ p_dbus_message_iter_open_container(&st_iter, DBUS_TYPE_ARRAY, "y", &pixels_arr_iter); -+ /* write pixels */ -+ num_pixels = icon_width * icon_height; -+ for( i=0; i<num_pixels * 4; i++ ) /* ARGB32 = 4 bytes per pixel */ -+ { -+ pixel_byte = img_data[i]; -+ p_dbus_message_iter_append_basic(&pixels_arr_iter, DBUS_TYPE_BYTE, &pixel_byte); -+ } -+ p_dbus_message_iter_close_container(&st_iter, &pixels_arr_iter); -+ p_dbus_message_iter_close_container(&a_iter, &st_iter); -+ } -+ p_dbus_message_iter_close_container(&v_iter, &a_iter); -+ p_dbus_message_iter_close_container(&iter, &v_iter); -+ return reply; -+} -+ -+ -+static DBusMessage *create_reply_propget_tooltip( -+ DBusMessage *msg, -+ const char *icon_name, -+ int icon_width, -+ int icon_height, -+ const unsigned char *img_data, -+ const char *tip_title, -+ const char *tip_text) -+{ -+ /* Format: (sa(iiay)ss) -+ * Components are: -+ * STRING: Freedesktop-compliant name for an icon. -+ * ARRAY(INT, INT, ARRAY BYTE): icon data -+ * STRING: title for this tooltip -+ * STRING: descriptive text for this tooltip. */ -+ DBusMessage *reply; -+ DBusMessageIter iter, v_iter, st_iter, arr_iter, ast_iter, pixels_arr_iter; -+ int num_pixels, i; -+ unsigned char pixel_byte; -+ -+ reply = p_dbus_message_new_method_return(msg); -+ if( !reply ) return FALSE; -+ -+ p_dbus_message_iter_init_append(reply, &iter); -+ p_dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "(sa(iiay)ss)", &v_iter); -+ p_dbus_message_iter_open_container(&v_iter, DBUS_TYPE_STRUCT, NULL, &st_iter); -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &icon_name); -+ p_dbus_message_iter_open_container(&st_iter, DBUS_TYPE_ARRAY, "(iiay)", &arr_iter); -+ /* write icon data, if set */ -+ if( (icon_height > 0) && (icon_width > 0) && (img_data)) { -+ p_dbus_message_iter_open_container(&arr_iter, DBUS_TYPE_STRUCT, NULL, &ast_iter); -+ /* write icon width, height */ -+ p_dbus_message_iter_append_basic(&ast_iter, DBUS_TYPE_INT32, &icon_width); -+ p_dbus_message_iter_append_basic(&ast_iter, DBUS_TYPE_INT32, &icon_height); -+ /* write icon bytes data as array */ -+ p_dbus_message_iter_open_container(&ast_iter, DBUS_TYPE_ARRAY, "y", &pixels_arr_iter); -+ /* write pixels */ -+ num_pixels = icon_width * icon_height; -+ for( i=0; i<num_pixels * 4; i++ ) /* ARGB32 = 4 bytes per pixel */ -+ { -+ pixel_byte = img_data[i]; -+ p_dbus_message_iter_append_basic(&pixels_arr_iter, DBUS_TYPE_BYTE, &pixel_byte); -+ } -+ p_dbus_message_iter_close_container(&ast_iter, &pixels_arr_iter); -+ p_dbus_message_iter_close_container(&arr_iter, &ast_iter); -+ } -+ p_dbus_message_iter_close_container(&st_iter, &arr_iter); -+ /* write tooltip title and text */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &tip_title); -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &tip_text); -+ p_dbus_message_iter_close_container(&v_iter, &st_iter); -+ p_dbus_message_iter_close_container(&iter, &v_iter); -+ return reply; -+} -+ -+ -+/* Appends dict value [attr_name] = variant(string value) to DBus -+ * reply for Properties.GetAll() */ -+static void reply_propgetall_append_s( -+ DBusMessageIter *piter, -+ const char *attr_name, -+ const char *value) -+{ -+ DBusMessageIter dict_iter, var_iter; -+ p_dbus_message_iter_open_container(piter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter); /* open dict */ -+ p_dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name); /* write attr name as dict key */ -+ p_dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, "s", &var_iter); /* open variant */ -+ p_dbus_message_iter_append_basic(&var_iter, DBUS_TYPE_STRING, &value); /* write attr value as Variant(string) */ -+ p_dbus_message_iter_close_container(&dict_iter, &var_iter); /* close variant */ -+ p_dbus_message_iter_close_container(piter, &dict_iter); /* close dict */ -+} -+ -+ -+/* Appends dict value [attr_name] = variant(uint32 value) to DBus -+ * reply for Properties.GetAll() */ -+static void reply_propgetall_append_u( -+ DBusMessageIter *piter, -+ const char *attr_name, -+ dbus_uint32_t value) -+{ -+ DBusMessageIter dict_iter, var_iter; -+ p_dbus_message_iter_open_container(piter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter); /* open dict */ -+ p_dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name); /* write attr name as dict key */ -+ p_dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, "u", &var_iter); /* open variant */ -+ p_dbus_message_iter_append_basic(&var_iter, DBUS_TYPE_UINT32, &value); /* write attr value as Variant(uint32) */ -+ p_dbus_message_iter_close_container(&dict_iter, &var_iter); /* close variant */ -+ p_dbus_message_iter_close_container(piter, &dict_iter); /* close dict */ -+} -+ -+ -+/* Appends dict value [attr_name] = variant(pixmap structure) to DBus -+ * reply for Properties.GetAll() */ -+static void reply_propgetall_append_pixmap( -+ DBusMessageIter *piter, -+ const char *attr_name, -+ int width, -+ int height, -+ const unsigned char *img_data) -+{ -+ DBusMessageIter dict_iter, var_iter, arr_iter, st_iter, pixels_arr_iter; -+ int num_pixels, i; -+ unsigned char pixel_byte; -+ -+ p_dbus_message_iter_open_container(piter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter); /* open dict */ -+ p_dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name); /* write attr name as dict key */ -+ p_dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, "a(iiay)", &var_iter); /* open variant */ -+ /* key value - pixmap array inside Variant -+ * example: "AttentionIconPixmap" = [Variant: [Argument: a(iiay) {}]] */ -+ p_dbus_message_iter_open_container(&var_iter, DBUS_TYPE_ARRAY, "(iiay)", &arr_iter); -+ if( (width > 0) && (height > 0) && (img_data)) { -+ /* open structure container */ -+ p_dbus_message_iter_open_container(&arr_iter, DBUS_TYPE_STRUCT, NULL, &st_iter); -+ /* write icon size: width, height */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_INT32, &width); -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_INT32, &height); -+ /* write icon bytes data as array */ -+ /* open array */ -+ p_dbus_message_iter_open_container(&st_iter, DBUS_TYPE_ARRAY, "y", &pixels_arr_iter); -+ /* write pixels */ -+ num_pixels = width * height; -+ for( i=0; i<num_pixels * 4; i++ ) /* ARGB32 = 4 bytes per pixel */ -+ { -+ pixel_byte = img_data[i]; -+ p_dbus_message_iter_append_basic(&pixels_arr_iter, DBUS_TYPE_BYTE, &pixel_byte); -+ } -+ /* close array */ -+ p_dbus_message_iter_close_container(&st_iter, &pixels_arr_iter); -+ /* close structure container */ -+ p_dbus_message_iter_close_container(&arr_iter, &st_iter); -+ } -+ p_dbus_message_iter_close_container(&var_iter, &arr_iter); /* close pixmaps array */ -+ p_dbus_message_iter_close_container(&dict_iter, &var_iter); /* close variant */ -+ p_dbus_message_iter_close_container(piter, &dict_iter); /* close dict */ -+} -+ -+ -+/* Appends dict value [attr_name] = variant(tooltip structure) to DBus -+ * reply for Properties.GetAll() */ -+static void reply_propgetall_append_tooltip( -+ DBusMessageIter *piter, -+ const char *attr_name, -+ const char *icon_name, -+ int width, -+ int height, -+ const unsigned char *img_data, -+ const char *tt_title, -+ const char *tt_text) -+{ -+ DBusMessageIter dict_iter, var_iter, st_iter, arr_iter, st2_iter, pixels_arr_iter; -+ int num_pixels, i; -+ unsigned char pixel_byte; -+ -+ p_dbus_message_iter_open_container(piter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter); /* open dict */ -+ p_dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attr_name); /* write attr name as dict key */ -+ p_dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, "(sa(iiay)ss)", &var_iter); /* open variant */ -+ /* key value - struct (sa(iiay)ss) */ -+ p_dbus_message_iter_open_container(&var_iter, DBUS_TYPE_STRUCT, NULL, &st_iter); /* open struct */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &icon_name); /* icon name */ -+ p_dbus_message_iter_open_container(&st_iter, DBUS_TYPE_ARRAY, "(iiay)", &arr_iter); /* open array */ -+ /* icon(s), but here only one */ -+ if( (width > 0) && (height > 0) && (img_data)) { -+ /* open structure container */ -+ p_dbus_message_iter_open_container(&arr_iter, DBUS_TYPE_STRUCT, NULL, &st2_iter); -+ /* write icon size: width, height */ -+ p_dbus_message_iter_append_basic(&st2_iter, DBUS_TYPE_INT32, &width); -+ p_dbus_message_iter_append_basic(&st2_iter, DBUS_TYPE_INT32, &height); -+ /* write icon bytes data as array */ -+ /* open array */ -+ p_dbus_message_iter_open_container(&st2_iter, DBUS_TYPE_ARRAY, "y", &pixels_arr_iter); -+ /* write pixels */ -+ num_pixels = width * height; -+ for( i=0; i<num_pixels * 4; i++ ) /* ARGB32 = 4 bytes per pixel */ -+ { -+ pixel_byte = img_data[i]; -+ p_dbus_message_iter_append_basic(&pixels_arr_iter, DBUS_TYPE_BYTE, &pixel_byte); -+ } -+ /* close array */ -+ p_dbus_message_iter_close_container(&st2_iter, &pixels_arr_iter); -+ /* close structure container */ -+ p_dbus_message_iter_close_container(&arr_iter, &st2_iter); -+ } -+ /* end icon */ -+ p_dbus_message_iter_close_container(&st_iter, &arr_iter); /* close array */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &tt_title); /* tooltip title */ -+ p_dbus_message_iter_append_basic(&st_iter, DBUS_TYPE_STRING, &tt_text); /* tooltip text */ -+ p_dbus_message_iter_close_container(&var_iter, &st_iter); /* close struct */ -+ -+ p_dbus_message_iter_close_container(&dict_iter, &var_iter); /* close variant */ -+ p_dbus_message_iter_close_container(piter, &dict_iter); /* close dict */ -+} -+ -+ -+/* DBus error replies */ -+ -+ -+static dbus_bool_t error_reply_failed(DBusMessage *message) -+{ -+ DBusMessage *reply; -+ dbus_bool_t ret; -+ reply = p_dbus_message_new_error(message, DBUS_ERROR_FAILED, "operation failed"); -+ if (!reply) return FALSE; -+ ret = dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+} -+ -+ -+static dbus_bool_t error_reply_unknown_interface(DBusMessage *message, const char *iface) -+{ -+ char error_message[256] = {0}; -+ DBusMessage *reply; -+ dbus_bool_t ret; -+ snprintf(error_message, sizeof(error_message)-1, "Unknown interface: [%s]", iface); -+ reply = p_dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_INTERFACE, error_message); -+ if (!reply) return FALSE; -+ ret = dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+} -+ -+ -+static dbus_bool_t error_reply_invalid_args(DBusMessage *message) -+{ -+ DBusMessage *reply; -+ dbus_bool_t ret; -+ reply = p_dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Invalid arguments!"); -+ if (!reply) return FALSE; -+ ret = dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+} -+ -+ -+static dbus_bool_t error_reply_unknown_property(DBusMessage *message, const char *prop_name) -+{ -+ DBusMessage *reply; -+ dbus_bool_t ret; -+ char error_message[256]; -+ snprintf(error_message, sizeof(error_message)-1, "Unknown property: [%s]", prop_name); -+ reply = p_dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_PROPERTY, error_message); -+ if (!reply) return FALSE; -+ ret = dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+} -+ -+ -+static dbus_bool_t error_reply_read_only_prop(DBusMessage *message, const char *prop_name) -+{ -+ char error_message[256]; -+ DBusMessage *reply; -+ dbus_bool_t ret; -+ snprintf(error_message, sizeof(error_message)-1, "property: %s", prop_name); -+ reply = p_dbus_message_new_error(message, DBUS_ERROR_PROPERTY_READ_ONLY, error_message); -+ if (!reply) return FALSE; -+ ret = dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+} -+ -+ -+/* DBus signals */ -+/* Emits DBus signal named "signal_name" */ -+static dbus_bool_t send_signal_noargs(const char *signal_name) -+{ -+ dbus_bool_t retb; -+ DBusMessage *msg; -+ msg = p_dbus_message_new_signal( -+ "/StatusNotifierItem", -+ "org.kde.StatusNotifierItem", -+ signal_name); -+ if (!msg) return FALSE; -+ retb = dbus_send_safe(msg); -+ p_dbus_message_unref(msg); -+ return retb; -+} -+ -+ -+/* Emits DBus signal "NetStatus(status)" */ -+static dbus_bool_t send_signal_NewStatus(const char *status) -+{ -+ dbus_bool_t retb; -+ DBusMessage *msg; -+ msg = p_dbus_message_new_signal( -+ "/StatusNotifierItem", -+ "org.kde.StatusNotifierItem", -+ "NewStatus"); -+ if (!msg) return FALSE; -+ /* apppend one argument - new status */ -+ p_dbus_message_append_args(msg, -+ DBUS_TYPE_STRING, &status, -+ DBUS_TYPE_INVALID); -+ retb = dbus_send_safe(msg); -+ p_dbus_message_unref(msg); -+ return retb; -+} -+ -+ -+/* Posts callback windows message to icon owner about tray mouse event */ -+static void relay_windows_message(struct tray_icon *icon, UINT uMsg) -+{ -+ BOOL ret; -+ DWORD cur_time; -+ /* store the last time mouse button was pressed */ -+ static DWORD last_L_time = 0; -+ static DWORD last_M_time = 0; -+ static DWORD last_R_time = 0; -+ -+ if (!icon->callback_message) return; -+ -+ TRACE("DBus: relaying 0x%x\n", uMsg); -+ -+ /* uMsg - application-defined callback message, -+ * wParam - icon id (defined by application, -+ * lParam - mouse message, e.g. WM_LBUTTONDOWN */ -+ ret = PostMessageW(icon->owner, icon->callback_message, (WPARAM)icon->id, (LPARAM)uMsg); -+ /* as in systray.c:469, check that window was valid */ -+ if (!ret && (GetLastError() == ERROR_INVALID_WINDOW_HANDLE)) -+ { -+ WARN( "application window was destroyed, removing icon %s\n", icon->dbus_name ); -+ delete_icon( icon ); -+ } -+ -+ /* Emulate mouse double button clicks */ -+ /* StatusNotifierItem does not have a notification for double clicks, but -+ * we can detect 2 fast single clicks as one double */ -+ cur_time = GetTickCount(); -+ switch( uMsg ) -+ { -+ case WM_LBUTTONDOWN: -+ if (cur_time - last_L_time < GetDoubleClickTime()) -+ PostMessageW(icon->owner, icon->callback_message, -+ (WPARAM)icon->id, (LPARAM)WM_LBUTTONDBLCLK); -+ last_L_time = cur_time; -+ break; -+ case WM_RBUTTONDOWN: -+ if (cur_time - last_R_time < GetDoubleClickTime()) -+ PostMessageW(icon->owner, icon->callback_message, -+ (WPARAM)icon->id, (LPARAM)WM_RBUTTONDBLCLK); -+ last_R_time = cur_time; -+ break; -+ case WM_MBUTTONDOWN: -+ if (cur_time - last_M_time < GetDoubleClickTime()) -+ PostMessageW(icon->owner, icon->callback_message, -+ (WPARAM)icon->id, (LPARAM)WM_MBUTTONDBLCLK); -+ last_M_time = cur_time; -+ break; -+ } -+} -+ -+ -+/************************************************************** -+ DBus message handlers -+***************************************************************/ -+ -+static void root_message_handler_unreg(DBusConnection *conn, void *user_data) -+{ -+ UNREFERENCED_PARAMETER(conn); /* unused */ -+ UNREFERENCED_PARAMETER(user_data); /* unused */ -+ TRACE("DBus: root object was unregistered\n"); -+} -+ -+ -+static DBusHandlerResult root_message_handler( -+ DBusConnection *conn, -+ DBusMessage *msg, -+ void *user_data ) -+{ -+ DBusHandlerResult ret; -+ DBusMessage *reply; -+ dbus_bool_t resb; -+ DBusError derror; -+ const char *mpath, *mintf, *mmemb, *mdest, *msig; -+ char *req_intf, *req_prop; -+ struct tray_icon *icon; -+ char tiptext_a[128]; -+ DBusMessageIter iter, arr_iter; -+ -+ UNREFERENCED_PARAMETER(user_data); /* unused */ -+ -+ /* probably, default fallback handler should always -+ * mark message as handled, otherwise it will cause errors */ -+ ret = DBUS_HANDLER_RESULT_HANDLED; -+ -+ /* Get message information */ -+ mpath = p_dbus_message_get_path(msg); -+ mintf = p_dbus_message_get_interface(msg); -+ mmemb = p_dbus_message_get_member(msg); -+ mdest = p_dbus_message_get_destination(msg); -+ msig = p_dbus_message_get_signature(msg); -+ -+ TRACE("DBus: message for path [%s] dest [%s], intf [%s].[%s]\n", -+ mpath, mdest, mintf, mmemb); -+ -+ p_dbus_error_init( &derror ); -+ -+ if (p_dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) -+ { -+ reply = NULL; -+ if (strcmp(mpath, "/") == 0) /* request for root object */ -+ { -+ reply = create_introspect_reply(msg, g_dbus_introspect_xml_root_with_SNI); -+ } -+ else if (strcmp(mpath, "/StatusNotifierItem") == 0) /* request for SNI object */ -+ { -+ reply = create_introspect_reply(msg, g_dbus_introspect_xml_SNI); -+ } -+ if (reply) -+ { -+ TRACE( "Introspect reply for path %s\n", mpath ); -+ dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ } -+ return ret; -+ } -+ -+ if (strcmp(mpath, "/StatusNotifierItem") == 0) -+ { -+ /* all messages for /StatusNotifierItem go here */ -+ /* Example: -+ * DBus: message for path [/StatusNotifierItem] -+ * dest [org.kde.StatusNotifierItem-19965-1], -+ * intf [org.freedesktop.DBus.Properties].[GetAll]: -+ * this is SNI host requesting all our icon properties */ -+ -+ /* try to find our icon that request was for */ -+ icon = get_icon_from_list_by_dname(mdest); -+ if (!icon) -+ { -+ WARN( "DBus: cannot find icon struct for DBus name [%s]\n", mdest ); -+ error_reply_failed(msg); -+ return ret; -+ } -+ -+ /* tests for which method is called */ -+ if (p_dbus_message_is_method_call(msg, "org.freedesktop.DBus.Properties", "Get") ) -+ { -+ if (strcmp(msig, "ss")) -+ { -+ /* incorrect call signature, must be 2 string arguments */ -+ error_reply_invalid_args(msg); -+ return ret; -+ } -+ resb = p_dbus_message_get_args(msg, &derror, -+ DBUS_TYPE_STRING, &req_intf, -+ DBUS_TYPE_STRING, &req_prop, -+ DBUS_TYPE_INVALID ); -+ if (resb == FALSE) -+ { -+ error_reply_invalid_args(msg); -+ return ret; -+ } -+ TRACE("DBus: call [%s] Properties.Get([%s], [%s])\n", mintf, req_intf, req_prop); -+ -+ /* check that they request this interface */ -+ if (strcmp(req_intf, "org.kde.StatusNotifierItem")) -+ { -+ WARN( "DBus: Properties.Get(): unknown interface requested: [%s]\n", req_intf ); -+ error_reply_unknown_interface(msg, req_intf); -+ return ret; -+ } -+ -+ reply = NULL; -+ -+ if(strcmp(req_prop, "Category") == 0) { -+ reply = create_reply_propget_s(msg, "ApplicationStatus"); -+ /* other categories: ApplicationStatus, Communications, SystemServices, Hardware */ -+ } else if(strcmp(req_prop, "Id") == 0) { -+ reply = create_reply_propget_s(msg, icon->sni_title); -+ } else if(strcmp(req_prop, "Title") == 0) { -+ WideCharToMultiByte(CP_ACP, 0, icon->tiptext, -1, tiptext_a, sizeof(tiptext_a), NULL, NULL); -+ reply = create_reply_propget_s(msg, tiptext_a); -+ } else if(strcmp(req_prop, "Status") == 0) { -+ reply = create_reply_propget_s(msg, "Active"); -+ /* other values: Active, Passive, NeedsAttention */ -+ } else if(strcmp(req_prop, "WindowId") == 0) { -+ Window w = X11DRV_get_whole_window( icon->owner ); -+ reply = create_reply_propget_u(msg, (dbus_uint32_t)w); -+ } else if(strcmp(req_prop, "IconName") == 0) { -+ if (icon->icon_data && (icon->icon_w > 0) && (icon->icon_h > 0)) -+ { -+ /* If we have actual icon image data, send empty icon name */ -+ reply = create_reply_propget_s(msg, ""); -+ } -+ else -+ { -+ /* otherwise, as fallback, use wine icon */ -+ reply = create_reply_propget_s(msg, "wine"); -+ } -+ } else if(strcmp(req_prop, "OverlayIconName") == 0) { -+ reply = create_reply_propget_s(msg, ""); -+ } else if(strcmp(req_prop, "AttentionIconName") == 0) { -+ reply = create_reply_propget_s(msg, ""); -+ } else if(strcmp(req_prop, "AttentionMovieName") == 0) { -+ reply = create_reply_propget_s(msg, ""); -+ } else if(strcmp(req_prop, "IconPixmap") == 0) { -+ /* send actual icon pixels */ -+ reply = create_reply_propget_pixmap(msg, icon->icon_w, icon->icon_h, icon->icon_data); -+ } else if(strcmp(req_prop, "OverlayIconPixmap") == 0) { -+ reply = create_reply_propget_pixmap(msg, 0, 0, NULL); -+ } else if(strcmp(req_prop, "AttentionIconPixmap") == 0) { -+ reply = create_reply_propget_pixmap(msg, 0, 0, NULL); -+ } else if(strcmp(req_prop, "ToolTip") == 0) { -+ WideCharToMultiByte(CP_ACP, 0, icon->tiptext, -1, tiptext_a, sizeof(tiptext_a), NULL, NULL); -+ if (icon->icon_data && (icon->icon_w > 0) && (icon->icon_h > 0)) -+ { -+ /* If we have actual icon image data, send empty icon name and real image data */ -+ reply = create_reply_propget_tooltip(msg, -+ "", /* icon name */ -+ icon->icon_w, icon->icon_h, icon->icon_data, /* icon data */ -+ tiptext_a, /* tip title (szTip member of NOTIFYICONDATA) */ -+ ""); /* tip text, empty */ -+ } -+ else -+ { -+ reply = create_reply_propget_tooltip(msg, -+ "wine", /* icon name */ -+ 0, 0, NULL, /* icon data */ -+ tiptext_a, /* tip title (szTip member of NOTIFYICONDATA) */ -+ ""); /* tip text, empty */ -+ } -+ } else { -+ WARN("DBus: unknown property requested: [%s]\n", req_prop); -+ error_reply_unknown_property(msg, req_prop); -+ } -+ -+ if (reply) -+ { -+ TRACE( "Propget reply for icon %s\n", icon->dbus_name ); -+ dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+ } -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.freedesktop.DBus.Properties", "Set")) -+ { -+ if (strcmp(msig, "ssv")) -+ { -+ error_reply_invalid_args(msg); -+ return ret; -+ } -+ -+ resb = p_dbus_message_get_args(msg, &derror, -+ DBUS_TYPE_STRING, &req_intf, -+ DBUS_TYPE_STRING, &req_prop, -+ DBUS_TYPE_INVALID ); -+ -+ /* check that they request this interface */ -+ if (strcmp(req_intf, "org.kde.StatusNotifierItem")) -+ { -+ WARN( "DBus: Properties.Set(): unknown interface requested: [%s]\n", req_intf ); -+ error_reply_unknown_interface(msg, req_intf); -+ return ret; -+ } -+ -+ if (resb == TRUE) -+ { -+ TRACE( "DBus: call [%s] Properties.Set([%s], [%s]): replying \"read-only\"\n", mintf, req_intf, req_prop); -+ error_reply_read_only_prop(msg, req_prop); -+ } -+ else -+ { -+ error_reply_read_only_prop(msg, "FAILED_TO_GET_PROP_NAME"); -+ } -+ return ret; -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.freedesktop.DBus.Properties", "GetAll")) -+ { -+ if (strcmp(msig, "s")) -+ { -+ error_reply_invalid_args(msg); -+ return ret; -+ } -+ -+ resb = p_dbus_message_get_args(msg, &derror, -+ DBUS_TYPE_STRING, &req_intf, -+ DBUS_TYPE_INVALID ); -+ if( resb == FALSE ) { -+ ERR( "DBus: Properties.GetAll(): Failed to get message args!\n" ); -+ error_reply_failed(msg); -+ return ret; -+ } -+ TRACE( "DBus: Properties.GetAll( \"%s\" )\n", req_intf ); -+ -+ /* check that they request this interface */ -+ if (strcmp(req_intf, "org.kde.StatusNotifierItem")) -+ { -+ WARN( "DBus: unknown interface requested: [%s]\n", req_intf ); -+ error_reply_unknown_interface(msg, req_intf); -+ return ret; -+ } -+ -+ /* okay, respond with all our "properties" */ -+ reply = p_dbus_message_new_method_return(msg); -+ if (!reply) -+ { -+ error_reply_failed(msg); -+ return ret; -+ } -+ -+ WideCharToMultiByte(CP_ACP, 0, icon->tiptext, -1, tiptext_a, sizeof(tiptext_a), NULL, NULL); -+ -+ /* create reply */ -+ p_dbus_message_iter_init_append(reply, &iter); -+ p_dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &arr_iter); /* open array */ -+ /* insert all object properties, contained in Variants */ -+ reply_propgetall_append_s(&arr_iter, "Category", "ApplicationStatus"); -+ reply_propgetall_append_s(&arr_iter, "Id", icon->sni_title); /* seems to be unused by KDE 5 */ -+ reply_propgetall_append_s(&arr_iter, "Title", tiptext_a); -+ /* ^^ this is also an icon identifier used by KDE Plasma 5 systray setting utility */ -+ reply_propgetall_append_s(&arr_iter, "Status", "Active"); -+ reply_propgetall_append_u(&arr_iter, "WindowId", 0); -+ /* ^^ KDE sends this as int32, not uint32... what? */ -+ if (icon->icon_data && (icon->icon_w > 0) && (icon->icon_h > 0)) -+ { -+ /* we have actual icon image data, send empty icon name */ -+ reply_propgetall_append_s(&arr_iter, "IconName", ""); -+ } -+ else -+ { -+ /* we don't have icon pixels, fallback: use standard wine icon */ -+ /* this is used as icon name in freedesktop icon theme */ -+ reply_propgetall_append_s(&arr_iter, "IconName", "wine"); -+ } -+ reply_propgetall_append_s(&arr_iter, "OverlayIconName", ""); -+ reply_propgetall_append_s(&arr_iter, "AttentionIconName", ""); -+ reply_propgetall_append_s(&arr_iter, "AttentionMovieName", ""); -+ reply_propgetall_append_pixmap(&arr_iter, "IconPixmap", -+ icon->icon_w, -+ icon->icon_h, -+ icon->icon_data); -+ reply_propgetall_append_pixmap(&arr_iter, "OverlayIconPixmap", 0, 0, NULL); -+ reply_propgetall_append_pixmap(&arr_iter, "AttentionIconPixmap", 0, 0, NULL); -+ if (icon->icon_data && (icon->icon_w > 0) && (icon->icon_h > 0)) -+ { -+ /* we have actual image data, send empty icon name and real pixels */ -+ reply_propgetall_append_tooltip( -+ &arr_iter, -+ "ToolTip", /* attribute name */ -+ "", /* icon name */ -+ icon->icon_w, /* icon width, */ -+ icon->icon_h, /* icon height, */ -+ icon->icon_data, /* icon image pixels */ -+ tiptext_a, /* tooltip title (this is szTip member if NOTIFYICONDATA) */ -+ "" /* tooltip text, empty */ -+ ); -+ } -+ else -+ { -+ /* we don't have actual image data, send "wine" icon name and no pixels */ -+ reply_propgetall_append_tooltip( -+ &arr_iter, -+ "ToolTip", /* attribute name */ -+ "wine", /* icon name */ -+ 0, /* icon width, */ -+ 0, /* icon height, */ -+ NULL, /* icon image pixels */ -+ tiptext_a, /* tooltip title (this is szTip member if NOTIFYICONDATA) */ -+ "" /* tooltip text, empty */ -+ ); -+ } -+ /* close array */ -+ p_dbus_message_iter_close_container(&iter, &arr_iter); -+ -+ TRACE( "Propgetall reply for icon %s\n", icon->dbus_name ); -+ dbus_send_safe(reply); -+ p_dbus_message_unref(reply); -+ return ret; -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.kde.StatusNotifierItem", "Activate")) -+ { -+ /* Left click on status icon -+ * VOID org.freedesktop.StatusNotifierItem.Activate (INT x, INT y); */ -+ TRACE( "org.kde.StatusNotifierItem:Activate()\n" ); -+ /* we ignore click coordinates here, because windows doesn't send it */ -+ relay_windows_message(icon, WM_LBUTTONDOWN); -+ relay_windows_message(icon, WM_LBUTTONUP); -+ /* TODO: should we emulate WM_MOUSEMOVE here? */ -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.kde.StatusNotifierItem", "ContextMenu")) -+ { -+ /* Right click on status icon -+ * VOID org.freedesktop.StatusNotifierItem.ContextMenu (INT x, INT y); */ -+ TRACE( "org.kde.StatusNotifierItem:ContextMenu()\n" ); -+ relay_windows_message(icon, WM_RBUTTONDOWN); -+ relay_windows_message(icon, WM_RBUTTONUP); -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.kde.StatusNotifierItem", "SecondaryActivate")) -+ { -+ /* Middle click on status icon -+ * VOID org.freedesktop.StatusNotifierItem.SecondaryActivate (INT x, INT y); */ -+ TRACE( "org.kde.StatusNotifierItem:SecondaryActivate()\n" ); -+ relay_windows_message(icon, WM_MBUTTONDOWN); -+ relay_windows_message(icon, WM_MBUTTONUP); -+ } -+ else if (p_dbus_message_is_method_call(msg, "org.kde.StatusNotifierItem", "Scroll")) -+ { -+ /* Mouse scroll over StatusNotifierItem -+ * VOID org.freedesktop.StatusNotifierItem.Scroll (INT delta, STRING orientation); -+ * orientation can be one of: "horizontal", "vertical" */ -+ TRACE( "org.kde.StatusNotifierItem:Scroll()\n" ); -+ /* Windows does not send any mouse scroll events, or even WM_VSCROLL :( */ -+ } -+ } -+ -+ /* Message handler can return one of these values: -+ * from enum DBusHandlerResult -+ * DBUS_HANDLER_RESULT_HANDLED - Message has had its effect, -+ no need to run more handlers. -+ * DBUS_HANDLER_RESULT_NOT_YET_HANDLED - Message has not had any effect, -+ see if other handlers want it. -+ * DBUS_HANDLER_RESULT_NEED_MEMORY - Please try again later with more memory. -+ */ -+ return ret; -+} -+ -+ -+/* DBus message loop thread function */ -+/* Infinite loop?? dlls/mountmgr.sys/dbus.c uses the similar approach! */ -+static DWORD WINAPI dbus_thread( void *arg ) -+{ -+ dbus_bool_t retb; -+ -+ UNREFERENCED_PARAMETER(arg); -+ if (!d_connection) return 1; -+ -+ retb = TRUE; -+ while (retb) -+ { -+ /* We call dbus_connection_send() when adding new icon, -+ * for example, this can lead to race condition. That's why -+ * there is a critical section here */ -+ EnterCriticalSection( &g_dconn_cs ); -+ /* reads data from socket (wait 100 ms) and calls message handler */ -+ retb = p_dbus_connection_read_write_dispatch( d_connection, 100 ); -+ LeaveCriticalSection( &g_dconn_cs ); -+ /* We need to release lock at least sometimes, that's why -+ * here is Sleep() call here with timeout of 100 ms */ -+ Sleep(100); -+ /* TODO: tweak timeouts? */ -+ } -+ -+ /* This infinite loop can break if there was some DBus error -+ * and connection was closed */ -+ WARN( "DBus: message loop has ended for some reason! Closing connection.\n" ); -+ -+ /* if we are here, we are probably not connected already */ -+ p_dbus_connection_unref(d_connection); -+ d_connection = NULL; -+ -+ /* mark as not running */ -+ g_dbus_thread_running = FALSE; -+ return 0; -+} -+ -+ -+/* Starts dbus message loop thread, if it's not already running */ -+static void start_dbus_thread(void) -+{ -+ HANDLE handle; -+ if (g_dbus_thread_running) return; -+ -+ handle = CreateThread( NULL, 0, dbus_thread, NULL, 0, NULL ); -+ if (handle) -+ { -+ g_dbus_thread_running = TRUE; -+ CloseHandle( handle ); -+ TRACE( "started dbus_thread\n" ); -+ } -+} -+ -+ -+/* Establishes connection to DBus session bus. -+ * Returns TRUE if connection is OK, FALSE otherwise. -+ * Returns TRUE immediately if already connected. */ -+static BOOL connect_dbus(void) -+{ -+ DBusError error; -+ DBusObjectPathVTable vtable; -+ dbus_bool_t resb; -+ -+ if (d_connection) return TRUE; /* already connected */ -+ p_dbus_error_init( &error ); -+ -+ if (!(d_connection = p_dbus_bus_get( DBUS_BUS_SESSION, &error ))) -+ { -+ WARN( "DBus: failed to connect to session bus: %s\n", error.message ); -+ p_dbus_error_free( &error ); -+ return FALSE; -+ } -+ -+ /* we do not want to exit(1) on any DBus error! */ -+ p_dbus_connection_set_exit_on_disconnect(d_connection, FALSE); -+ -+ /* Register default message handler for root DBus object "/" */ -+ ZeroMemory(&vtable, sizeof(vtable)); -+ vtable.unregister_function = root_message_handler_unreg; -+ vtable.message_function = root_message_handler; -+ resb = p_dbus_connection_try_register_fallback( -+ d_connection, -+ "/", /* object path */ -+ &vtable, /* message handler functions */ -+ NULL, /* user_data */ -+ &error); -+ if( resb == FALSE ) -+ { -+ WARN("DBus: ERROR: Failed to register DBus root object " -+ "message handler! Error: %s\n", error.message); -+ p_dbus_error_free( &error ); -+ return FALSE; -+ } -+ -+ /* Run read/write dispatcher. This will actually call message handler, -+ * if there are any messages incoming (and they are there). -+ * The first message will be signal 'NameAcquired' from DBus -+ * example: "DBus: message for path [/org/freedesktop/DBus] dest [:1.58], -+ * intf [org.freedesktop.DBus].[NameAcquired]" */ -+ p_dbus_connection_read_write_dispatch(d_connection, 0); -+ /* Of course, we will want real DBus message loop later, for real icons */ -+ -+ TRACE( "DBus: connected to SESSION bus as '%s'.\n", -+ p_dbus_bus_get_unique_name(d_connection) ); -+ return TRUE; -+} -+ -+ -+static void disconnect_dbus(void) -+{ -+ if (d_connection) { -+ p_dbus_connection_unregister_object_path(d_connection, "/"); -+ p_dbus_connection_read_write_dispatch(d_connection, 0); -+ p_dbus_connection_unref(d_connection); -+ d_connection = NULL; -+ TRACE( "DBus: disconnected.\n" ); -+ } -+} -+ -+ -+/* Check if org.kde.StatusNotifierWatcher is running on DBus, and read its -+ * property IsStatusNotifierHostRegistered to determine if we can -+ * use DBus StatusNotifierItem tray. */ -+static BOOL is_statusnotifier_host_running(void) -+{ -+ DBusError error; -+ DBusMessage *msg, *reply; -+ const char *iface_name; -+ const char *property_name; -+ DBusMessageIter iter; -+ DBusMessageIter sub_iter; -+ dbus_bool_t is_sni_host_running = FALSE; -+ int arg_type; -+ -+ if (!d_connection) return FALSE; -+ p_dbus_error_init( &error ); -+ -+ /* Check that there is StatusNotifierWatcher on bus. -+ * According to DBus docs, this method can cause race condition, -+ * StatusNotifierWatcher can disappear any time after this method -+ * was called, but in that case the following DBus method call -+ * will simply fail anyway. */ -+ if (p_dbus_bus_name_has_owner( -+ d_connection, "org.kde.StatusNotifierWatcher", &error)) -+ { -+ TRACE( "DBus: detected that org.kde.StatusNotifierWatcher present, " -+ "will ask him about StatusNotifierHost!\n" ); -+ /* We need to read property "IsStatusNotifierHostRegistered" -+ * of interface "org.kde.StatusNotifierWatcher" -+ * which is on path "/StatusNotifierWatcher" -+ * So, we need to call org.freedesktop.DBus.Properties.Get(...) on that -+ * interface */ -+ msg = p_dbus_message_new_method_call( -+ "org.kde.StatusNotifierWatcher", /* bus name */ -+ "/StatusNotifierWatcher", /* path */ -+ "org.freedesktop.DBus.Properties", /* interface */ -+ "Get"); /* method */ -+ if (msg) -+ { -+ /* Get() method has 2 parameters - interface name and -+ * property name, set them */ -+ iface_name = "org.kde.StatusNotifierWatcher"; -+ property_name = "IsStatusNotifierHostRegistered"; -+ p_dbus_message_append_args(msg, -+ DBUS_TYPE_STRING, &iface_name, -+ DBUS_TYPE_STRING, &property_name, -+ DBUS_TYPE_INVALID); -+ /* send request and wait for reply for 1000 ms */ -+ reply = p_dbus_connection_send_with_reply_and_block( -+ d_connection, msg, -+ 1000, /* timeout in ms */ -+ &error); -+ if (reply) -+ { -+ /* reply from org.kde.StatusNotifierWatcher will contain -+ * Variant(bool), although in specification -+ * org.freedesktop.StatusNotifierWatcher should return -+ * simply bool, instead of Variant(bool) !!! */ -+ if (p_dbus_message_iter_init(reply, &iter)) -+ { -+ /* Read only first message argument. Either it is -+ * Bool, or Variant(bool) */ -+ arg_type = p_dbus_message_iter_get_arg_type(&iter); -+ if (arg_type == DBUS_TYPE_VARIANT) -+ { -+ /* Variant(bool), recurse read iterator into Variant type */ -+ p_dbus_message_iter_recurse(&iter, &sub_iter); -+ /* read its contained value */ -+ arg_type = p_dbus_message_iter_get_arg_type(&sub_iter); -+ if (arg_type == DBUS_TYPE_BOOLEAN) -+ { -+ p_dbus_message_iter_get_basic(&sub_iter, &is_sni_host_running); -+ TRACE( "DBus: OK: Got prop.get reply, " -+ "IsStatusNotifierHostRegistered = %u\n", -+ (unsigned)is_sni_host_running ); -+ } -+ } -+ else if (arg_type == DBUS_TYPE_BOOLEAN) -+ { -+ /* simply bool */ -+ p_dbus_message_iter_get_basic(&iter, &is_sni_host_running); -+ TRACE( "DBus: OK: Got prop.get reply, " -+ "IsStatusNotifierHostRegistered = %u\n", -+ (unsigned)is_sni_host_running ); -+ } -+ } -+ p_dbus_message_unref(reply); -+ p_dbus_message_unref(msg); -+ return (is_sni_host_running ? TRUE : FALSE); -+ } -+ /* reply == NULL here, some error has happened */ -+ WARN( "DBus: error requesting property from StatusNotifierWatcher: " -+ "%s", error.message ); -+ p_dbus_error_free( &error ); -+ p_dbus_message_unref(msg); -+ return FALSE; -+ } -+ WARN( "DBus: Failed to create new DBus message!\n" ); -+ return FALSE; -+ } -+ TRACE( "DBus: name org.kde.StatusNotifierWatcher is not found on bus.\n" ); -+ return FALSE; -+} -+ -+ -+#endif /* SONAME_LIBDBUS_1 */ -+ -+ -+/* Check if Wine can use DBus StatusNotifierItem specification -+ * to implement system tray icons. This should be called from -+ * systray.c: wine_notify_icon() when performing tray icon operations. -+ * -+ * Returns TRUE, if compiled with DBus support and StatusNotifierHost -+ * is detected running, FALSE otherwise. */ -+BOOL can_use_dbus_sni_systray(void) -+{ -+#ifdef SONAME_LIBDBUS_1 -+ static int using_dbus_sni_systray = -1; /* -1 = unknown */ -+ -+ /* This environment variable can be set to completely disable -+ * DBus-powered StatusNotifierItem systray support */ -+ if (getenv("WINE_DISABLE_SNI_SYSTRAY")) -+ { -+ TRACE( "env: WINE_DISABLE_SNI_SYSTRAY: DBus SNI systray disabled.\n"); -+ return FALSE; -+ } -+ -+ if (using_dbus_sni_systray == FALSE) return FALSE; -+ if (using_dbus_sni_systray == TRUE) return TRUE; -+ -+ /* check that we can at least load DBus library */ -+ if (!initialize_dbus()) -+ { -+ using_dbus_sni_systray = FALSE; -+ TRACE( "Not enabling DBus systray support: cannot load DBus library\n" ); -+ return FALSE; -+ } -+ -+ /* check that we can connect to session bus */ -+ if (!connect_dbus()) -+ { -+ using_dbus_sni_systray = FALSE; -+ return FALSE; -+ } -+ -+ /* check that there is a StatusNotifierHost present */ -+ if (is_statusnotifier_host_running()) -+ { -+ TRACE( "DBus: detected that we can use DBus systray instead of XEmbed\n" ); -+ /* Do not disconnect from DBus here, we will probably use -+ * this connection to manage status notifier items later ;) */ -+ using_dbus_sni_systray = TRUE; -+ return TRUE; -+ } -+ -+ /* No DBus/SNI system tray detected, disconnect DBus and return FALSE */ -+ disconnect_dbus(); -+ -+ TRACE( "DBus: No DBus/SNI system tray was detected.\n" ); -+ return FALSE; -+#else -+ /* Compiled without DBus support? Cannot use DBus at all */ -+ TRACE( "Compiled without DBus support, cannot use DBus SNI systray\n" ); -+ return FALSE; -+#endif -+} -+ -+ -+static void assign_tray_icon_data(struct tray_icon *icon, NOTIFYICONDATAW *nid) -+{ -+ ICONINFO iconinfo; -+ BITMAP bmColor; -+ HBITMAP hbmColorCopy; -+ DWORD icon_data_size; -+ -+ /* copy state flags */ -+ if (nid->uFlags & NIF_STATE) -+ { -+ icon->state = (icon->state & ~nid->dwStateMask) | (nid->dwState & nid->dwStateMask); -+ } -+ /* copy icon */ -+ if (nid->uFlags & NIF_ICON) -+ { -+ /* delete old icon, if any */ -+ if (icon->image) DestroyIcon(icon->image); -+ if (icon->icon_data) HeapFree(GetProcessHeap(), 0, icon->icon_data); -+ icon->image = NULL; -+ icon->icon_data = NULL; -+ icon->icon_w = icon->icon_h = 0; -+ -+ /* set new icon */ -+ if (nid->hIcon) -+ { -+ icon->image = CopyIcon(nid->hIcon); -+ if (GetIconInfo(nid->hIcon, &iconinfo)) -+ { -+ TRACE( "fIcon = %u, (hotspot %d, %d) mask = %p, color = %p\n", iconinfo.fIcon, -+ iconinfo.xHotspot, iconinfo.yHotspot, -+ iconinfo.hbmMask, iconinfo.hbmColor); -+ TRACE( "System icon size: %d x %d\n", GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) ); -+ -+ ZeroMemory(&bmColor, sizeof(BITMAP)); -+ -+ if (iconinfo.hbmColor) -+ { -+ hbmColorCopy = CopyImage(iconinfo.hbmColor, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); -+ if (hbmColorCopy) -+ { -+ GetObjectW(hbmColorCopy, sizeof(BITMAP), &bmColor); -+ /* MSDN: If hgdiobj is a handle to a bitmap created by any other means, -+ * (not by CreateDIBSection) GetObject returns only the width, height, -+ * and color format information of the bitmap. You can obtain the bitmap's -+ * bit values by calling the GetDIBits or GetBitmapBits function. -+ * But we created bitmap copy with LR_CREATEDIBSECTION, and we HAVE -+ * bits pointer! */ -+ TRACE( "Got color bitmap: bmType = %d\n", bmColor.bmType ); -+ TRACE( " size = %d x %d\n", bmColor.bmWidth, bmColor.bmHeight ); -+ TRACE( " scanline bytes = %d\n", bmColor.bmWidthBytes ); -+ TRACE( " color planes = %d\n", (int)bmColor.bmPlanes ); -+ TRACE( " bits per pixel = %d\n", (int)bmColor.bmBitsPixel ); -+ TRACE( " bits pointer = %p\n", bmColor.bmBits ); -+ -+ /* SNI spec says image format must be ARGB32, so we handle only 32(24)-bit image */ -+ if (bmColor.bmBits && (bmColor.bmBitsPixel == 32)) -+ { -+ /* image data size = w * h * (bits_per_pixel / 8) */ -+ icon_data_size = bmColor.bmWidth * bmColor.bmHeight * bmColor.bmBitsPixel / 8; -+ icon->icon_data = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, icon_data_size); -+ if (icon->icon_data) -+ { -+ unsigned char *row_dst, *row_src; -+ int irow, j; -+ ZeroMemory(icon->icon_data, icon_data_size); -+ row_dst = icon->icon_data; -+ row_src = (unsigned char *)bmColor.bmBits; -+ /* make row_src point to lat row, to flip image bottom to top */ -+ row_src += ((bmColor.bmHeight - 1) * bmColor.bmWidthBytes); -+ for (irow = 0; irow < bmColor.bmHeight; irow++) -+ { -+ for (j=0; j<bmColor.bmWidthBytes; j+=4) -+ { -+ /* change byte order so that BGRA (as in RGBQUAD structure -+ * becomes ARGB, as required by SNI spec */ -+ row_dst[j + 0] = row_src[j + 3]; /* B -> A */ -+ row_dst[j + 1] = row_src[j + 2]; /* G -> R */ -+ row_dst[j + 2] = row_src[j + 1]; /* R -> G */ -+ row_dst[j + 3] = row_src[j + 0]; /* A -> B */ -+ } -+ row_src -= bmColor.bmWidthBytes; /* move 1 row backward */ -+ row_dst += bmColor.bmWidthBytes; /* move 1 row forward */ -+ } -+ /* memcpy(icon->icon_data, bmColor.bmBits, icon_data_size); */ -+ icon->icon_w = (int)bmColor.bmWidth; -+ icon->icon_h = (int)bmColor.bmHeight; -+ TRACE( "Saved icon bitmap, %u bytes\n", icon_data_size ); -+ } -+ } -+ -+ DeleteObject(hbmColorCopy); -+ } -+ } -+ if (iconinfo.hbmMask) DeleteObject(iconinfo.hbmMask); -+ if (iconinfo.hbmColor) DeleteObject(iconinfo.hbmColor); -+ } -+ } -+ } -+ /* copy callback message */ -+ if (nid->uFlags & NIF_MESSAGE) -+ { -+ icon->callback_message = nid->uCallbackMessage; -+ } -+ /* copy tooltip data */ -+ if (nid->uFlags & NIF_TIP) -+ { -+ lstrcpynW(icon->tiptext, nid->szTip, sizeof(icon->tiptext)/sizeof(WCHAR)); -+ } -+ /* copy balloon popup data */ -+ if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) -+ { -+ /* has balloon popup members */ -+ lstrcpynW( icon->info_text, nid->szInfo, sizeof(icon->info_text)/sizeof(WCHAR) ); -+ lstrcpynW( icon->info_title, nid->szInfoTitle, sizeof(icon->info_title)/sizeof(WCHAR) ); -+ icon->info_flags = nid->dwInfoFlags; -+ icon->info_timeout = max(min(nid->u.uTimeout, BALLOON_SHOW_MAX_TIMEOUT), BALLOON_SHOW_MIN_TIMEOUT); -+ icon->info_icon = nid->hBalloonIcon; -+ } -+} -+ -+ -+BOOL add_sni_icon(NOTIFYICONDATAW *nid) -+{ -+#ifdef SONAME_LIBDBUS_1 -+ struct tray_icon *icon; -+ int res; -+ dbus_bool_t resb; -+ DBusError derror; -+ DBusMessage *req; -+ char *NPE_FIX; -+ DWORD owner_pid; -+ -+ TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); -+ -+ /* check if icon already exists */ -+ if ((icon = get_icon_from_list(nid->hWnd, nid->uID))) -+ { -+ WARN("DBus: duplicate tray icon add, buggy app?\n"); -+ return FALSE; -+ } -+ -+ /* allocate new icon struct and add it to list */ -+ icon = add_new_icon_to_list(); -+ if (!icon) return FALSE; -+ -+ /* init structure members */ -+ icon->id = nid->uID; -+ icon->owner = nid->hWnd; -+ icon->display = -1; /* display index, or -1 if hidden */ -+ -+ assign_tray_icon_data(icon, nid); -+ -+ /* Ensure that dbus message loop is running */ -+ start_dbus_thread(); -+ -+ /* request some particular name on session bus */ -+ /* Format: org.kde.StatusNotifierItem-PID-ICONID */ -+ GetWindowThreadProcessId(icon->owner, &owner_pid); -+ snprintf(icon->dbus_name, sizeof(icon->dbus_name)-1, -+ "org.kde.StatusNotifierItem-%u-%u", -+ owner_pid, nid->uID); -+ -+ p_dbus_error_init( &derror ); -+ -+ TRACE( "Requesting name [%s]...\n", icon->dbus_name ); -+ EnterCriticalSection( &g_dconn_cs ); -+ res = p_dbus_bus_request_name(d_connection, icon->dbus_name, -+ DBUS_NAME_FLAG_DO_NOT_QUEUE, &derror); -+ LeaveCriticalSection( &g_dconn_cs ); -+ if( res != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { -+ ERR("DBus: Request name failed! Not primary owner! code=%d\n", res); -+ ERR("DBus error: %s\n", derror.message); -+ p_dbus_error_free( &derror ); -+ return FALSE; -+ } -+ TRACE( "Request name [%s] OK!\n", icon->dbus_name ); -+ -+ /* calculate and store title that will be used in several places -+ * - as a tooltip title, popup title -+ * - as icon identifier, maybe -+ * ideally it should be process name */ -+ /*HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, owner_pid); -+ if (hProcess) -+ { -+ GetProcessImageFileNameA(hProcess, icon->sni_title, sizeof(icon->sni_title)-1) -+ CloseHandle(hProcess); -+ } */ -+ /* This requires linking to psapi.dll and include "psapi.h" :/ */ -+ -+ /* GetModuleFileNameA(NULL, icon->sni_title, sizeof(icon->sni_title)-1); */ -+ /* ^^ This returns [C:\windows\system32\explorer.exe], because winex11.drv is loaded -+ * by explorer.exe? But we cannot use it as icon identifier then :) */ -+ -+ /* TRACE( "command line: [%s]\n", GetCommandLineA() ); */ -+ /* [C:\windows\system32\explorer.exe /desktop], the same, cannot use */ -+ -+ lstrcpynA(icon->sni_title, "wine", sizeof(icon->sni_title)-1); -+ -+ TRACE( "Using [%s] as application name\n", icon->sni_title ); -+ -+ /* Try to communicate with StatusNotifierWatcher: -+ * tell him that we are here and we have a status icon! */ -+ req = p_dbus_message_new_method_call( -+ "org.kde.StatusNotifierWatcher", /* dest */ -+ "/StatusNotifierWatcher", /* path */ -+ "org.kde.StatusNotifierWatcher", /* iface */ -+ "RegisterStatusNotifierItem" /* method */ -+ ); -+ /* we need to pass him our BUS NAME in message */ -+ NPE_FIX = strdup(icon->dbus_name); -+ if( NPE_FIX ) { -+ p_dbus_message_append_args(req, -+ DBUS_TYPE_STRING, &NPE_FIX, -+ DBUS_TYPE_INVALID); -+ free(NPE_FIX); -+ } -+ resb = dbus_send_safe(req); -+ if (resb == FALSE) -+ { -+ WARN("dbus_connection_send() failed: cannot register our SNI!\n"); -+ p_dbus_message_unref(req); -+ return FALSE; -+ } -+ -+ return TRUE; -+#else -+ /* complied without DBus support */ -+ UNREFERENCED_PARAMETER(nid); -+ return FALSE; -+#endif -+} -+ -+ -+BOOL modify_sni_icon(NOTIFYICONDATAW *nid) -+{ -+#ifdef SONAME_LIBDBUS_1 -+ struct tray_icon *icon; -+ -+ TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); -+ -+ icon = get_icon_from_list(nid->hWnd, nid->uID); -+ if (!icon) return FALSE; -+ -+ /* update structure members */ -+ assign_tray_icon_data(icon, nid); -+ -+ /* icon has changed? */ -+ if (nid->uFlags & NIF_ICON) -+ { -+ /* icon data was already updated by assign_tray_icon_data() */ -+ /* Notify SNI host about it */ -+ send_signal_noargs( "NewIcon" ); -+ } -+ -+ /* szTip has changed? */ -+ if (nid->uFlags & NIF_TIP) -+ { -+ /* Notify SNI host about new tooltip */ -+ send_signal_noargs( "NewToolTip" ); -+ } -+ -+ /* balloon popup was updated? */ -+ if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) -+ { -+ /* Notify SNI host that our icon needs attention */ -+ /* actually it was active all the time, but maybe it will change in future */ -+ send_signal_NewStatus( "NeedsAttention" ); /* possible values: Active, Passive, NeedsAttention */ -+ /* TODO: deal with balloon */ -+ /* update_balloon( icon ); */ -+ } -+ -+ /* TODO: implement hiding icon? -+ if (icon->state & NIS_HIDDEN) hide_icon( icon ); -+ else show_icon( icon ); -+ */ -+ -+ /* We don't use these SNI signals: NewTitle, NewAttentionIcon, NewOverlayIcon */ -+ -+ return TRUE; -+#else -+ /* complied without DBus support */ -+ UNREFERENCED_PARAMETER(nid); -+ return FALSE; -+#endif -+} -+ -+ -+static BOOL delete_icon(struct tray_icon *icon) -+{ -+ BOOL ret; -+ int res; -+ DBusError derror; -+ -+ if (!d_connection) return FALSE; -+ -+ /* Release dedicated SNI bus name */ -+ p_dbus_error_init( &derror ); -+ res = p_dbus_bus_release_name(d_connection, icon->dbus_name, &derror); -+ if( res != DBUS_RELEASE_NAME_REPLY_RELEASED ) { -+ WARN( "DBus: Release name failed! Err code=%d\n", res ); -+ WARN( "DBus error: %s\n", derror.message ); -+ ret = FALSE; -+ } else { -+ TRACE( "DBus: Name released [%s] OK!\n", icon->dbus_name ); -+ ret = TRUE; -+ } -+ -+ /* Do not forget to delete hIcon ? */ -+ if (icon->image) DestroyIcon(icon->image); -+ if (icon->icon_data) HeapFree(GetProcessHeap(), 0, icon->icon_data); -+ icon->image = NULL; -+ icon->icon_data = NULL; -+ icon->icon_w = icon->icon_h = 0; -+ -+ delete_icon_from_list( icon ); -+ return ret; -+} -+ -+ -+ -+BOOL delete_sni_icon(NOTIFYICONDATAW *nid) -+{ -+#ifdef SONAME_LIBDBUS_1 -+ struct tray_icon *icon; -+ -+ TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); -+ -+ icon = get_icon_from_list(nid->hWnd, nid->uID); -+ if (!icon) return FALSE; -+ -+ return delete_icon( icon ); -+#else -+ /* complied without DBus support */ -+ UNREFERENCED_PARAMETER(nid); -+ return FALSE; -+#endif -+} --- |