diff --git a/app-emulation/wine/patches/wine-6.23.patchset b/app-emulation/wine/patches/wine-6.23.patchset new file mode 100644 index 000000000..73e1491e5 --- /dev/null +++ b/app-emulation/wine/patches/wine-6.23.patchset @@ -0,0 +1,5890 @@ +From a7d16839941f7bb34820c2579aeaf48b7f4868f2 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Fri, 31 Dec 2021 08:17:23 +0900 +Subject: Haiku: fix build and minimal operation + +--- + dlls/nsiproxy.sys/ndis.c | 10 ++++++++ + dlls/ntdll/unix/file.c | 2 ++ + dlls/ntdll/unix/loader.c | 4 +++ + dlls/ntdll/unix/serial.c | 2 ++ + dlls/ntdll/unix/server.c | 3 +++ + dlls/ntdll/unix/signal_x86_64.c | 45 +++++++++++++++++++++++++++++++++ + dlls/ntdll/unix/socket.c | 7 +++++ + dlls/winex11.drv/bitblt.c | 1 + + dlls/ws2_32/unixlib.c | 6 +++++ + server/change.c | 3 +++ + server/fd.c | 3 +++ + server/signal.c | 3 +++ + server/sock.c | 8 ++++++ + 13 files changed, 97 insertions(+) + +diff --git a/dlls/nsiproxy.sys/ndis.c b/dlls/nsiproxy.sys/ndis.c +index 3e37bcecc78..ed8e206657b 100644 +--- a/dlls/nsiproxy.sys/ndis.c ++++ b/dlls/nsiproxy.sys/ndis.c +@@ -264,6 +264,9 @@ static WCHAR *strdupAtoW( const char *str ) + + static struct if_entry *add_entry( DWORD index, char *name ) + { ++#ifdef __HAIKU__ ++ return NULL; ++#else + struct if_entry *entry; + int name_len = strlen( name ); + +@@ -292,6 +295,7 @@ static struct if_entry *add_entry( DWORD index, char *name ) + + list_add_tail( &if_list, &entry->entry ); + return entry; ++#endif + } + + static void update_if_table( void ) +@@ -327,6 +331,7 @@ static void ifinfo_fill_dynamic( struct if_entry *entry, struct nsi_ndis_ifinfo_ + fd = socket( PF_INET, SOCK_DGRAM, 0 ); + if (fd == -1) return; + ++#ifndef __HAIKU__ + if (!ioctl( fd, SIOCGIFFLAGS, &req )) + { + if (req.ifr_flags & IFF_UP) data->oper_status = IfOperStatusUp; +@@ -335,6 +340,7 @@ static void ifinfo_fill_dynamic( struct if_entry *entry, struct nsi_ndis_ifinfo_ + #endif + else data->oper_status = IfOperStatusDown; + } else data->oper_status = IfOperStatusUnknown; ++#endif + + data->flags.unk = 0; + data->flags.not_media_conn = 0; +@@ -342,8 +348,12 @@ static void ifinfo_fill_dynamic( struct if_entry *entry, struct nsi_ndis_ifinfo_ + data->media_conn_state = MediaConnectStateConnected; + data->unk = 0; + ++#ifndef __HAIKU__ + if (!ioctl( fd, SIOCGIFMTU, &req )) data->mtu = req.ifr_mtu; + else data->mtu = 0; ++#else ++ data->mtu = 0; ++#endif + + close( fd ); + +diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c +index 10d8f3de4a3..43e21056a0a 100644 +--- a/dlls/ntdll/unix/file.c ++++ b/dlls/ntdll/unix/file.c +@@ -6529,6 +6529,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io + } + + if (!get_mountmgr_fs_info( handle, fd, &drive, sizeof(drive) )) fs_type = drive.fs_type; ++#ifndef __HAIKU__ + else + { + struct statfs stfs; +@@ -6560,6 +6561,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io + #endif + } + } ++#endif + + switch (fs_type) + { +diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c +index 82d099de3be..a1e4515616f 100644 +--- a/dlls/ntdll/unix/loader.c ++++ b/dlls/ntdll/unix/loader.c +@@ -870,7 +870,11 @@ static NTSTATUS map_so_dll( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ) + + sizeof(IMAGE_NT_HEADERS) + + nb_sections * sizeof(IMAGE_SECTION_HEADER)); + ++#ifdef __HAIKU__ ++ mprotect(addr, size, PROT_READ | PROT_WRITE); ++#else + if (anon_mmap_fixed( addr, size, PROT_READ | PROT_WRITE, 0 ) != addr) return STATUS_NO_MEMORY; ++#endif + + dos = (IMAGE_DOS_HEADER *)addr; + nt = (IMAGE_NT_HEADERS *)((BYTE *)(dos + 1) + sizeof(builtin_signature)); +diff --git a/dlls/ntdll/unix/serial.c b/dlls/ntdll/unix/serial.c +index 83244d02d41..6d1d27c749e 100644 +--- a/dlls/ntdll/unix/serial.c ++++ b/dlls/ntdll/unix/serial.c +@@ -280,9 +280,11 @@ static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc) + switch (port.c_cflag & CSIZE) + { + case CS5: slc->WordLength = 5; break; ++#ifndef __HAIKU__ + case CS6: slc->WordLength = 6; break; + case CS7: slc->WordLength = 7; break; + case CS8: slc->WordLength = 8; break; ++#endif + default: ERR("unknown size %x\n", (UINT)(port.c_cflag & CSIZE)); + } + +diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c +index 1dcd0792072..e6eb2c39a71 100644 +--- a/dlls/ntdll/unix/server.c ++++ b/dlls/ntdll/unix/server.c +@@ -76,6 +76,9 @@ + #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 + #endif + #endif ++#ifdef __HAIKU__ ++#define SIGIO SIGPOLL ++#endif + + #include "ntstatus.h" + #define WIN32_NO_STATUS +diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c +index 9e9a96db832..957f796444b 100644 +--- a/dlls/ntdll/unix/signal_x86_64.c ++++ b/dlls/ntdll/unix/signal_x86_64.c +@@ -64,6 +64,11 @@ + #ifdef __APPLE__ + # include + #endif ++#ifdef __HAIKU__ ++# include ++extern status_t _kern_generic_syscall(const char *subsystem, uint32 function, ++ void *buffer, size_t bufferSize); ++#endif + + #define NONAMELESSUNION + #define NONAMELESSSTRUCT +@@ -232,6 +237,34 @@ __ASM_GLOBAL_FUNC( alloc_fs_sel, + #define FPU_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw) + #define XState_sig(context) NULL + ++#elif defined (__HAIKU__) ++ ++#define RAX_sig(context) ((context)->uc_mcontext.rax) ++#define RBX_sig(context) ((context)->uc_mcontext.rbx) ++#define RCX_sig(context) ((context)->uc_mcontext.rcx) ++#define RDX_sig(context) ((context)->uc_mcontext.rdx) ++#define RSI_sig(context) ((context)->uc_mcontext.rsi) ++#define RDI_sig(context) ((context)->uc_mcontext.rdi) ++#define RBP_sig(context) ((context)->uc_mcontext.rbp) ++#define R8_sig(context) ((context)->uc_mcontext.r8) ++#define R9_sig(context) ((context)->uc_mcontext.r9) ++#define R10_sig(context) ((context)->uc_mcontext.r10) ++#define R11_sig(context) ((context)->uc_mcontext.r11) ++#define R12_sig(context) ((context)->uc_mcontext.r12) ++#define R13_sig(context) ((context)->uc_mcontext.r13) ++#define R14_sig(context) ((context)->uc_mcontext.r14) ++#define R15_sig(context) ((context)->uc_mcontext.r15) ++#define CS_sig(context) NULL ++#define FS_sig(context) NULL ++#define GS_sig(context) NULL ++#define EFL_sig(context) ((context)->uc_mcontext.rflags) ++#define RIP_sig(context) ((context)->uc_mcontext.rip) ++#define RSP_sig(context) ((context)->uc_mcontext.rsp) ++#define TRAP_sig(context) TRAP_x86_PAGEFLT ++#define ERROR_sig(context) 0 ++#define FPU_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext.fpu) ++#define XState_sig(context) NULL ++ + #else + #error You must define the signal context functions for your platform + #endif +@@ -1511,10 +1544,12 @@ static inline void set_sigcontext( const CONTEXT *context, ucontext_t *sigcontex + R14_sig(sigcontext) = context->R14; + R15_sig(sigcontext) = context->R15; + RIP_sig(sigcontext) = context->Rip; ++#ifndef __HAIKU__ + CS_sig(sigcontext) = context->SegCs; + FS_sig(sigcontext) = context->SegFs; + GS_sig(sigcontext) = context->SegGs; + EFL_sig(sigcontext) = context->EFlags; ++#endif + #ifdef DS_sig + DS_sig(sigcontext) = context->SegDs; + #endif +@@ -2171,7 +2206,9 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec + } + } + ++#ifndef __HAIKU__ + CS_sig(sigcontext) = cs64_sel; ++#endif + RIP_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher; + RSP_sig(sigcontext) = (ULONG_PTR)stack; + /* clear single-step, direction, and align check flag */ +@@ -2550,6 +2587,12 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) + EXCEPTION_RECORD rec = { 0 }; + struct xcontext context; + ucontext_t *ucontext = sigcontext; ++ printf("segv_handler\n"); ++ printf(" IP: %#" PRIx64 "\n", RIP_sig(ucontext)); ++ printf(" SP: %#" PRIx64 "\n", RSP_sig(ucontext)); ++ printf(" FP: %#" PRIx64 "\n", RBP_sig(ucontext)); ++ printf(" address: %#" PRIx64 "\n", siginfo->si_addr); ++ _exit(1); + + rec.ExceptionAddress = (void *)RIP_sig(ucontext); + save_context( &context, sigcontext ); +@@ -2911,6 +2954,8 @@ void signal_init_thread( TEB *teb ) + thread's gsbase. Have each thread record its gsbase pointer into its + TEB so alloc_tls_slot() can find it. */ + teb->Reserved5[0] = amd64_thread_data()->pthread_teb; ++#elif defined (__HAIKU__) ++ _kern_generic_syscall("thread", /*THREAD_SET_GS_BASE*/ 1, teb, 0); + #else + # error Please define setting %gs for your architecture + #endif +diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c +index 2e79b9baa0f..335b9fa8ed6 100644 +--- a/dlls/ntdll/unix/socket.c ++++ b/dlls/ntdll/unix/socket.c +@@ -168,7 +168,9 @@ static NTSTATUS sock_errno_to_status( int err ) + case EDESTADDRREQ: return STATUS_INVALID_PARAMETER; + case EMSGSIZE: return STATUS_BUFFER_OVERFLOW; + case EPROTONOSUPPORT: ++#ifndef __HAIKU__ + case ESOCKTNOSUPPORT: ++#endif + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EPROTOTYPE: return STATUS_NOT_SUPPORTED; +@@ -1450,11 +1452,16 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc + } + else + { ++#ifdef __HAIKU__ ++ status = sock_errno_to_status( -1 ); ++ break; ++#else + if ((ret = ioctl( fd, SIOCATMARK, &value )) < 0) + { + status = sock_errno_to_status( errno ); + break; + } ++#endif + /* windows is reversed with respect to unix */ + *(int *)out_buffer = !value; + } +diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c +index fad183b0b01..fe47611d8bf 100644 +--- a/dlls/winex11.drv/bitblt.c ++++ b/dlls/winex11.drv/bitblt.c +@@ -41,6 +41,7 @@ + # include + # endif + #endif ++#undef HAVE_LIBXXSHM + + #include "windef.h" + #include "winbase.h" +diff --git a/dlls/ws2_32/unixlib.c b/dlls/ws2_32/unixlib.c +index 67edf06368e..4b9274bf867 100644 +--- a/dlls/ws2_32/unixlib.c ++++ b/dlls/ws2_32/unixlib.c +@@ -166,7 +166,9 @@ static const int ip_protocol_map[][2] = + MAP( IPPROTO_ICMP ), + MAP( IPPROTO_IGMP ), + MAP( IPPROTO_RAW ), ++#ifndef __HAIKU__ + {WS_IPPROTO_IPV4, IPPROTO_IPIP}, ++#endif + }; + + #undef MAP +@@ -338,7 +340,9 @@ static unsigned int errno_from_unix( int err ) + case EPROTOTYPE: return WSAEPROTOTYPE; + case ENOPROTOOPT: return WSAENOPROTOOPT; + case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; ++#ifndef __HAIKU__ + case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; ++#endif + case EOPNOTSUPP: return WSAEOPNOTSUPP; + case EPFNOSUPPORT: return WSAEPFNOSUPPORT; + case EAFNOSUPPORT: return WSAEAFNOSUPPORT; +@@ -354,7 +358,9 @@ static unsigned int errno_from_unix( int err ) + case EISCONN: return WSAEISCONN; + case ENOTCONN: return WSAENOTCONN; + case ESHUTDOWN: return WSAESHUTDOWN; ++#ifndef __HAIKU__ + case ETOOMANYREFS: return WSAETOOMANYREFS; ++#endif + case ETIMEDOUT: return WSAETIMEDOUT; + case ECONNREFUSED: return WSAECONNREFUSED; + case ELOOP: return WSAELOOP; +diff --git a/server/change.c b/server/change.c +index a01d6894151..a26f7d36214 100644 +--- a/server/change.c ++++ b/server/change.c +@@ -36,6 +36,9 @@ + #ifdef HAVE_SYS_INOTIFY_H + #include + #endif ++#ifdef __HAIKU__ ++#define SIGIO SIGPOLL ++#endif + + #include "ntstatus.h" + #define WIN32_NO_STATUS +diff --git a/server/fd.c b/server/fd.c +index c9a21186722..1a0840f4113 100644 +--- a/server/fd.c ++++ b/server/fd.c +@@ -88,6 +88,9 @@ + #ifdef HAVE_SYS_SYSCALL_H + #include + #endif ++#ifdef __HAIKU__ ++#undef ioctl ++#endif + + #include "ntstatus.h" + #define WIN32_NO_STATUS +diff --git a/server/signal.c b/server/signal.c +index 19b76d44c16..05dafe154f5 100644 +--- a/server/signal.c ++++ b/server/signal.c +@@ -28,6 +28,9 @@ + #include + #endif + #include ++#ifdef __HAIKU__ ++#define SIGIO SIGPOLL ++#endif + + #include "file.h" + #include "object.h" +diff --git a/server/sock.c b/server/sock.c +index c9b71137c4c..daeb937bf4e 100644 +--- a/server/sock.c ++++ b/server/sock.c +@@ -1483,7 +1483,9 @@ static int get_unix_protocol( int protocol ) + case WS_IPPROTO_ICMP: return IPPROTO_ICMP; + case WS_IPPROTO_IGMP: return IPPROTO_IGMP; + case WS_IPPROTO_IP: return IPPROTO_IP; ++#ifndef __HAIKU__ + case WS_IPPROTO_IPV4: return IPPROTO_IPIP; ++#endif + case WS_IPPROTO_IPV6: return IPPROTO_IPV6; + case WS_IPPROTO_RAW: return IPPROTO_RAW; + case WS_IPPROTO_TCP: return IPPROTO_TCP; +@@ -1943,7 +1945,9 @@ static unsigned int sock_get_error( int err ) + case EPROTOTYPE: return WSAEPROTOTYPE; + case ENOPROTOOPT: return WSAENOPROTOOPT; + case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; ++#ifndef __HAIKU__ + case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; ++#endif + case EOPNOTSUPP: return WSAEOPNOTSUPP; + case EPFNOSUPPORT: return WSAEPFNOSUPPORT; + case EAFNOSUPPORT: return WSAEAFNOSUPPORT; +@@ -1959,7 +1963,9 @@ static unsigned int sock_get_error( int err ) + case EISCONN: return WSAEISCONN; + case ENOTCONN: return WSAENOTCONN; + case ESHUTDOWN: return WSAESHUTDOWN; ++#ifndef __HAIKU__ + case ETOOMANYREFS: return WSAETOOMANYREFS; ++#endif + case ETIMEDOUT: return WSAETIMEDOUT; + case ECONNREFUSED: return WSAECONNREFUSED; + case ELOOP: return WSAELOOP; +@@ -2010,7 +2016,9 @@ static int sock_get_ntstatus( int err ) + case EDESTADDRREQ: return STATUS_INVALID_PARAMETER; + case EMSGSIZE: return STATUS_BUFFER_OVERFLOW; + case EPROTONOSUPPORT: ++#ifndef __HAIKU__ + case ESOCKTNOSUPPORT: ++#endif + case EPFNOSUPPORT: + case EAFNOSUPPORT: + case EPROTOTYPE: return STATUS_NOT_SUPPORTED; +-- +2.30.2 + + +From a598228f33d61990d18e09560d5028a018a22d91 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Sun, 16 Jan 2022 17:27:49 +0900 +Subject: winehaiku.drv: add + +--- + configure.ac | 1 + + dlls/winehaiku.drv/Makefile.in | 26 + + dlls/winehaiku.drv/clipboard.c | 105 ++ + dlls/winehaiku.drv/desktop.c | 45 + + dlls/winehaiku.drv/display.c | 96 ++ + dlls/winehaiku.drv/gdi.c | 163 +++ + dlls/winehaiku.drv/haikudrv.h | 307 ++++++ + dlls/winehaiku.drv/haikudrv_main.c | 109 ++ + dlls/winehaiku.drv/ime.c | 181 ++++ + dlls/winehaiku.drv/init.c | 103 ++ + dlls/winehaiku.drv/keyboard.c | 92 ++ + dlls/winehaiku.drv/mouse.c | 79 ++ + dlls/winehaiku.drv/settings.cpp | 74 ++ + dlls/winehaiku.drv/systray.c | 74 ++ + dlls/winehaiku.drv/version.rc | 22 + + dlls/winehaiku.drv/vidmode.c | 57 + + dlls/winehaiku.drv/vulkan.cpp | 418 ++++++++ + dlls/winehaiku.drv/window.cpp | 1393 +++++++++++++++++++++++++ + dlls/winehaiku.drv/winehaiku.drv.spec | 29 + + dlls/winehaiku.drv/wintab.c | 69 ++ + include/wine/server.h | 4 +- + include/wine/vulkan_driver.h | 40 +- + include/winuser.h | 2 +- + programs/explorer/desktop.c | 2 +- + 24 files changed, 3467 insertions(+), 24 deletions(-) + create mode 100644 dlls/winehaiku.drv/Makefile.in + create mode 100644 dlls/winehaiku.drv/clipboard.c + create mode 100644 dlls/winehaiku.drv/desktop.c + create mode 100644 dlls/winehaiku.drv/display.c + create mode 100644 dlls/winehaiku.drv/gdi.c + create mode 100644 dlls/winehaiku.drv/haikudrv.h + create mode 100644 dlls/winehaiku.drv/haikudrv_main.c + create mode 100644 dlls/winehaiku.drv/ime.c + create mode 100644 dlls/winehaiku.drv/init.c + create mode 100644 dlls/winehaiku.drv/keyboard.c + create mode 100644 dlls/winehaiku.drv/mouse.c + create mode 100644 dlls/winehaiku.drv/settings.cpp + create mode 100644 dlls/winehaiku.drv/systray.c + create mode 100644 dlls/winehaiku.drv/version.rc + create mode 100644 dlls/winehaiku.drv/vidmode.c + create mode 100644 dlls/winehaiku.drv/vulkan.cpp + create mode 100644 dlls/winehaiku.drv/window.cpp + create mode 100644 dlls/winehaiku.drv/winehaiku.drv.spec + create mode 100644 dlls/winehaiku.drv/wintab.c + +diff --git a/configure.ac b/configure.ac +index 4fdb1ef33df..c7b4e40cf5e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3547,6 +3547,7 @@ WINE_CONFIG_MAKEFILE(dlls/winepulse.drv) + WINE_CONFIG_MAKEFILE(dlls/wineusb.sys) + WINE_CONFIG_MAKEFILE(dlls/winevulkan) + WINE_CONFIG_MAKEFILE(dlls/winex11.drv) ++WINE_CONFIG_MAKEFILE(dlls/winehaiku.drv) + WINE_CONFIG_MAKEFILE(dlls/winexinput.sys) + WINE_CONFIG_MAKEFILE(dlls/wing.dll16,enable_win16) + WINE_CONFIG_MAKEFILE(dlls/wing32) +diff --git a/dlls/winehaiku.drv/Makefile.in b/dlls/winehaiku.drv/Makefile.in +new file mode 100644 +index 00000000000..0db76dd3a93 +--- /dev/null ++++ b/dlls/winehaiku.drv/Makefile.in +@@ -0,0 +1,26 @@ ++MODULE = winehaiku.drv ++IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32 win32u ++DELAYIMPORTS = comctl32 ole32 shell32 imm32 ++EXTRAINCL = -I/boot/system/develop/headers/private/shared ++EXTRALIBS = -lbe -lstdc++ -lvulkan ++ ++EXTRADLLFLAGS = -mcygwin ++ ++C_SRCS = \ ++ clipboard.c \ ++ desktop.c \ ++ display.c \ ++ ime.c \ ++ init.c \ ++ keyboard.c \ ++ mouse.c \ ++ settings.cpp \ ++ systray.c \ ++ window.cpp \ ++ wintab.c \ ++ haikudrv_main.c \ ++ vidmode.c \ ++ gdi.c \ ++ vulkan.cpp ++ ++RC_SRCS = version.rc +diff --git a/dlls/winehaiku.drv/clipboard.c b/dlls/winehaiku.drv/clipboard.c +new file mode 100644 +index 00000000000..8e840a543f1 +--- /dev/null ++++ b/dlls/winehaiku.drv/clipboard.c +@@ -0,0 +1,105 @@ ++/* ++ * X11 clipboard windows driver ++ * ++ * Copyright 1994 Martin Ayotte ++ * Copyright 1996 Alex Korobka ++ * Copyright 1999 Noel Borthwick ++ * Copyright 2003 Ulrich Czekalla for CodeWeavers ++ * Copyright 2014 Damjan Jovanovic ++ * Copyright 2016 Alexandre Julliard ++ * ++ * 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 ++ * ++ * NOTES: ++ * This file contains the X specific implementation for the windows ++ * Clipboard API. ++ * ++ * Wine's internal clipboard is exposed to external apps via the X ++ * selection mechanism. ++ * Currently the driver asserts ownership via two selection atoms: ++ * 1. PRIMARY(XA_PRIMARY) ++ * 2. CLIPBOARD ++ * ++ * In our implementation, the CLIPBOARD selection takes precedence over PRIMARY, ++ * i.e. if a CLIPBOARD selection is available, it is used instead of PRIMARY. ++ * When Wine takes ownership of the clipboard, it takes ownership of BOTH selections. ++ * While giving up selection ownership, if the CLIPBOARD selection is lost, ++ * it will lose both PRIMARY and CLIPBOARD and empty the clipboard. ++ * However if only PRIMARY is lost, it will continue to hold the CLIPBOARD selection ++ * (leaving the clipboard cache content unaffected). ++ * ++ * Every format exposed via a windows clipboard format is also exposed through ++ * a corresponding X selection target. A selection target atom is synthesized ++ * whenever a new Windows clipboard format is registered via RegisterClipboardFormat, ++ * or when a built-in format is used for the first time. ++ * Windows native format are exposed by prefixing the format name with "" ++ * This allows us to uniquely identify windows native formats exposed by other ++ * running WINE apps. ++ * ++ * In order to allow external applications to query WINE for supported formats, ++ * we respond to the "TARGETS" selection target. (See EVENT_SelectionRequest ++ * for implementation) We use the same mechanism to query external clients for ++ * availability of a particular format, by caching the list of available targets ++ * by using the clipboard cache's "delayed render" mechanism. If a selection client ++ * does not support the "TARGETS" selection target, we actually attempt to retrieve ++ * the format requested as a fallback mechanism. ++ * ++ * Certain Windows native formats are automatically converted to X native formats ++ * and vice versa. If a native format is available in the selection, it takes ++ * precedence, in order to avoid unnecessary conversions. ++ * ++ * FIXME: global format list needs a critical section ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#ifdef HAVE_UNISTD_H ++# include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#include "haikudrv.h" ++ ++#include "shlobj.h" ++#include "shellapi.h" ++#include "shlwapi.h" ++#include "wine/list.h" ++#include "wine/debug.h" ++#include "wine/unicode.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(clipboard); ++ ++ ++/************************************************************************** ++ * HAIKUDRV_UpdateClipboard ++ */ ++void CDECL HAIKUDRV_UpdateClipboard(void) ++{ ++} ++ ++/************************************************************************** ++ * HAIKUDRV_InitClipboard ++ */ ++void HAIKUDRV_InitClipboard(void) ++{ ++} +diff --git a/dlls/winehaiku.drv/desktop.c b/dlls/winehaiku.drv/desktop.c +new file mode 100644 +index 00000000000..c06e22e65a3 +--- /dev/null ++++ b/dlls/winehaiku.drv/desktop.c +@@ -0,0 +1,45 @@ ++/* ++ * HAIKUDRV desktop window handling ++ * ++ * Copyright 2001 Alexandre Julliard ++ * Copyright 2020 Zhiyi Zhang for CodeWeavers ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#define NONAMELESSSTRUCT ++#define NONAMELESSUNION ++ ++#include "haikudrv.h" ++ ++/* avoid conflict with field names in included win32 headers */ ++#undef Status ++#include "wine/debug.h" ++#include "wine/heap.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++ ++ ++/*********************************************************************** ++ * HAIKUDRV_create_desktop ++ * ++ * Create the X11 desktop window for the desktop mode. ++ */ ++BOOL CDECL HAIKUDRV_create_desktop( UINT width, UINT height ) ++{ ++ return FALSE; ++} +diff --git a/dlls/winehaiku.drv/display.c b/dlls/winehaiku.drv/display.c +new file mode 100644 +index 00000000000..d122ba270f2 +--- /dev/null ++++ b/dlls/winehaiku.drv/display.c +@@ -0,0 +1,96 @@ ++/* ++ * HAIKUDRV display device functions ++ * ++ * Copyright 2019 Zhiyi Zhang for CodeWeavers ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++#include "rpc.h" ++#include "winreg.h" ++#include "cfgmgr32.h" ++#include "initguid.h" ++#include "devguid.h" ++#include "devpkey.h" ++#include "ntddvdeo.h" ++#include "setupapi.h" ++#define WIN32_NO_STATUS ++#include "winternl.h" ++#include "wine/debug.h" ++#include "wine/unicode.h" ++#include "haikudrv.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++ ++ ++void CDECL HAIKUDRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, ++ BOOL force, void *param ) ++{ ++ INT gpu_count, adapter_count, monitor_count; ++ DWORD len; ++ static BOOL called = FALSE; ++ ++ if (!called) { ++ called = TRUE; ++ } else { ++ if (!force) return; ++ } ++ ++ for (int i = 0; i < 1; i++) ++ { ++ struct gdi_gpu gdi_gpu = ++ { ++ .id = 1, ++ .vendor_id = 0x1002, ++ .device_id = 0x683f, ++ .subsys_id = 0, ++ .revision_id = 0, ++ }; ++ const char *gpuName = "RADV VERDE"; ++ RtlUTF8ToUnicodeN(gdi_gpu.name, sizeof(gdi_gpu.name), &len, gpuName, strlen(gpuName)); ++ device_manager->add_gpu(&gdi_gpu, param); ++ ++ for (int j = 0; j < 1; j++) ++ { ++ struct gdi_adapter gdi_adapter = ++ { ++ .id = 1, ++ .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE, ++ }; ++ device_manager->add_adapter( &gdi_adapter, param ); ++ ++ for (int k = 0; k < 1; k++) ++ { ++ struct gdi_monitor gdi_monitor = ++ { ++ .rc_monitor = {0, 0, 1920, 1080}, ++ .rc_work = {0, 0, 1920, 1080}, ++ .state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE, ++ }; ++ const char *monitorName = "Generic Non-PnP Monitor"; ++ RtlUTF8ToUnicodeN(gdi_monitor.name, sizeof(gdi_monitor.name), &len, ++ monitorName, strlen(monitorName)); ++ device_manager->add_monitor( &gdi_monitor, param ); ++ } ++ ++ } ++ } ++} +diff --git a/dlls/winehaiku.drv/gdi.c b/dlls/winehaiku.drv/gdi.c +new file mode 100644 +index 00000000000..3bfc6bc9400 +--- /dev/null ++++ b/dlls/winehaiku.drv/gdi.c +@@ -0,0 +1,163 @@ ++#include "config.h" ++#include "haikudrv.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++ ++ ++typedef struct ++{ ++ struct gdi_physdev dev; ++} HAIKUDRV_PDEVICE; ++ ++static inline HAIKUDRV_PDEVICE *get_haikudrv_dev(PHYSDEV dev) ++{ ++ return (HAIKUDRV_PDEVICE*)dev; ++} ++ ++ ++/* a few dynamic device caps */ ++static int horz_size; /* horz. size of screen in millimeters */ ++static int vert_size; /* vert. size of screen in millimeters */ ++static int bits_per_pixel; /* pixel depth of screen */ ++static int device_data_valid; /* do the above variables have up-to-date values? */ ++ ++int retina_on = FALSE; ++ ++static CRITICAL_SECTION device_data_section; ++static CRITICAL_SECTION_DEBUG critsect_debug = ++{ ++ 0, 0, &device_data_section, ++ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, ++ 0, 0, { (DWORD_PTR)(__FILE__ ": device_data_section") } ++}; ++static CRITICAL_SECTION device_data_section = { &critsect_debug, -1, 0, 0, 0, 0 }; ++ ++ ++/********************************************************************** ++ * device_init ++ * ++ * Perform initializations needed upon creation of the first device. ++ */ ++static void device_init(void) ++{ ++ /* Initialize device caps */ ++ horz_size = 1920; ++ vert_size = 1080; ++ ++ bits_per_pixel = 32; ++ device_data_valid = TRUE; ++} ++ ++ ++void haikudrv_reset_device_metrics(void) ++{ ++ EnterCriticalSection(&device_data_section); ++ device_data_valid = FALSE; ++ LeaveCriticalSection(&device_data_section); ++} ++ ++ ++static HAIKUDRV_PDEVICE *create_haiku_physdev(void) ++{ ++ HAIKUDRV_PDEVICE *physDev; ++ ++ EnterCriticalSection(&device_data_section); ++ if (!device_data_valid) device_init(); ++ LeaveCriticalSection(&device_data_section); ++ ++ if (!(physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev)))) return NULL; ++ ++ return physDev; ++} ++ ++ ++/********************************************************************** ++ * CreateDC (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_CreateDC(PHYSDEV *pdev, LPCWSTR device, LPCWSTR output, ++ const DEVMODEW* initData) ++{ ++ HAIKUDRV_PDEVICE *physDev = create_haiku_physdev(); ++ ++ TRACE("pdev %p hdc %p device %s output %s initData %p\n", pdev, ++ (*pdev)->hdc, debugstr_w(device), debugstr_w(output), initData); ++ ++ if (!physDev) return FALSE; ++ ++ push_dc_driver(pdev, &physDev->dev, &haikudrv_funcs.dc_funcs); ++ return TRUE; ++} ++ ++ ++/********************************************************************** ++ * CreateCompatibleDC (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_CreateCompatibleDC(PHYSDEV orig, PHYSDEV *pdev) ++{ ++ HAIKUDRV_PDEVICE *physDev = create_haiku_physdev(); ++ ++ TRACE("orig %p orig->hdc %p pdev %p pdev->hdc %p\n", orig, (orig ? orig->hdc : NULL), pdev, ++ ((pdev && *pdev) ? (*pdev)->hdc : NULL)); ++ ++ if (!physDev) return FALSE; ++ ++ push_dc_driver(pdev, &physDev->dev, &haikudrv_funcs.dc_funcs); ++ return TRUE; ++} ++ ++ ++/********************************************************************** ++ * DeleteDC (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_DeleteDC(PHYSDEV dev) ++{ ++ HAIKUDRV_PDEVICE *physDev = get_haikudrv_dev(dev); ++ ++ TRACE("hdc %p\n", dev->hdc); ++ ++ HeapFree(GetProcessHeap(), 0, physDev); ++ return TRUE; ++} ++ ++ ++/*********************************************************************** ++ * GetDeviceCaps (HAIKUDRV.@) ++ */ ++INT CDECL HAIKUDRV_GetDeviceCaps(PHYSDEV dev, INT cap) ++{ ++ INT ret; ++ ++ TRACE("hdc %p\n", dev->hdc); ++ ++ EnterCriticalSection(&device_data_section); ++ ++ if (!device_data_valid) device_init(); ++ ++ switch(cap) ++ { ++ case HORZSIZE: ++ ret = horz_size; ++ break; ++ case VERTSIZE: ++ ret = vert_size; ++ break; ++ case BITSPIXEL: ++ ret = bits_per_pixel; ++ break; ++ case HORZRES: ++ case VERTRES: ++ default: ++ LeaveCriticalSection(&device_data_section); ++ dev = GET_NEXT_PHYSDEV( dev, pGetDeviceCaps ); ++ ret = dev->funcs->pGetDeviceCaps( dev, cap ); ++ if ((cap == HORZRES || cap == VERTRES) && retina_on) ++ ret *= 2; ++ return ret; ++ } ++ ++ TRACE("cap %d -> %d\n", cap, ret); ++ ++ LeaveCriticalSection(&device_data_section); ++ return ret; ++} +diff --git a/dlls/winehaiku.drv/haikudrv.h b/dlls/winehaiku.drv/haikudrv.h +new file mode 100644 +index 00000000000..65ffb414ab1 +--- /dev/null ++++ b/dlls/winehaiku.drv/haikudrv.h +@@ -0,0 +1,307 @@ ++/* ++ * X11 driver definitions ++ * ++ * Copyright 1996 Alexandre Julliard ++ * Copyright 1999 Patrik Stridvall ++ * ++ * 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_HAIKUDRV_H ++#define __WINE_HAIKUDRV_H ++ ++#ifndef __WINE_CONFIG_H ++# error You must include config.h to use this header ++#endif ++ ++#include ++ ++#undef Status /* avoid conflict with wintrnl.h */ ++typedef int Status; ++ ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "wine/gdi_driver.h" ++#include "wine/list.h" ++ ++#define MAX_DASHLEN 16 ++ ++#define WINE_XDND_VERSION 5 ++ ++static inline void reset_bounds( RECT *bounds ) ++{ ++ bounds->left = bounds->top = INT_MAX; ++ bounds->right = bounds->bottom = INT_MIN; ++} ++ ++static inline void add_bounds_rect( RECT *bounds, const RECT *rect ) ++{ ++ if (rect->left >= rect->right || rect->top >= rect->bottom) return; ++ bounds->left = min( bounds->left, rect->left ); ++ bounds->top = min( bounds->top, rect->top ); ++ bounds->right = max( bounds->right, rect->right ); ++ bounds->bottom = max( bounds->bottom, rect->bottom ); ++} ++ ++/* Wine driver X11 functions */ ++ ++extern BOOL CDECL HAIKUDRV_CreateDC(PHYSDEV *pdev, LPCWSTR device, LPCWSTR output, const DEVMODEW* initData); ++extern BOOL CDECL HAIKUDRV_CreateCompatibleDC(PHYSDEV orig, PHYSDEV *pdev); ++extern BOOL CDECL HAIKUDRV_DeleteDC(PHYSDEV dev); ++extern INT CDECL HAIKUDRV_GetDeviceCaps(PHYSDEV dev, INT cap); ++extern const struct vulkan_funcs *CDECL HAIKUDRV_wine_get_vulkan_driver(PHYSDEV dev, UINT version); ++ ++extern BOOL CDECL HAIKUDRV_ActivateKeyboardLayout( HKL hkl, UINT flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_Beep(void) DECLSPEC_HIDDEN; ++extern INT CDECL HAIKUDRV_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) DECLSPEC_HIDDEN; ++extern UINT CDECL HAIKUDRV_MapVirtualKeyEx( UINT code, UINT map_type, HKL hkl ) DECLSPEC_HIDDEN; ++extern INT CDECL HAIKUDRV_ToUnicodeEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState, ++ LPWSTR bufW, int bufW_size, UINT flags, HKL hkl ) DECLSPEC_HIDDEN; ++extern SHORT CDECL HAIKUDRV_VkKeyScanEx( WCHAR wChar, HKL hkl ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_DestroyCursorIcon( HCURSOR handle ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetCursor( HCURSOR handle ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_SetCursorPos( INT x, INT y ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_ClipCursor( LPCRECT clip ) DECLSPEC_HIDDEN; ++extern LONG CDECL HAIKUDRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, ++ HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, ++ DWORD flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, ++ BOOL force, void *param ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_CreateDesktopWindow( HWND hwnd ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_CreateWindow( HWND hwnd ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_FlashWindowEx( PFLASHWINFO pfinfo ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_GetDC( HDC hdc, HWND hwnd, HWND top, const RECT *win_rect, ++ const RECT *top_rect, DWORD flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_ReleaseDC( HWND hwnd, HDC hdc ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetCapture( HWND hwnd, UINT flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, ++ DWORD flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetWindowIcon( HWND hwnd, UINT type, HICON icon ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetWindowText( HWND hwnd, LPCWSTR text ) DECLSPEC_HIDDEN; ++extern UINT CDECL HAIKUDRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) DECLSPEC_HIDDEN; ++extern LRESULT CDECL HAIKUDRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_UpdateClipboard(void) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, ++ const RECT *window_rect ) DECLSPEC_HIDDEN; ++extern LRESULT CDECL HAIKUDRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, ++ const RECT *window_rect, const RECT *client_rect, RECT *visible_rect, ++ struct window_surface **surface ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, ++ const RECT *rectWindow, const RECT *rectClient, ++ const RECT *visible_rect, const RECT *valid_rects, ++ struct window_surface *surface ) DECLSPEC_HIDDEN; ++extern BOOL CDECL HAIKUDRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, ++ UINT flags ) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_ThreadDetach(void) DECLSPEC_HIDDEN; ++ ++/* X11 driver internal functions */ ++ ++extern RGNDATA *HAIKUDRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN; ++ ++/* IME support */ ++extern void IME_SetOpenStatus(BOOL fOpen) DECLSPEC_HIDDEN; ++extern void IME_SetCompositionStatus(BOOL fOpen) DECLSPEC_HIDDEN; ++extern INT IME_GetCursorPos(void) DECLSPEC_HIDDEN; ++extern void IME_SetCursorPos(DWORD pos) DECLSPEC_HIDDEN; ++extern void IME_UpdateAssociation(HWND focus) DECLSPEC_HIDDEN; ++extern BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, ++ DWORD dwCompLen, LPCVOID lpRead, ++ DWORD dwReadLen) DECLSPEC_HIDDEN; ++extern void IME_SetResultString(LPWSTR lpResult, DWORD dwResultlen) DECLSPEC_HIDDEN; ++ ++ ++/************************************************************************** ++ * X11 USER driver ++ */ ++ ++struct haikudrv_thread_data; ++ ++extern struct haikudrv_thread_data *haikudrv_init_thread_data(void) DECLSPEC_HIDDEN; ++extern DWORD thread_data_tls_index DECLSPEC_HIDDEN; ++ ++static inline struct haikudrv_thread_data *haikudrv_thread_data(void) ++{ ++ DWORD err = GetLastError(); /* TlsGetValue always resets last error */ ++ struct haikudrv_thread_data *data = (struct haikudrv_thread_data*)TlsGetValue( thread_data_tls_index ); ++ SetLastError( err ); ++ return data; ++} ++ ++extern BOOL clipping_cursor DECLSPEC_HIDDEN; ++extern BOOL keyboard_grabbed DECLSPEC_HIDDEN; ++extern unsigned int screen_bpp DECLSPEC_HIDDEN; ++extern BOOL use_xkb DECLSPEC_HIDDEN; ++extern BOOL usexrandr DECLSPEC_HIDDEN; ++extern BOOL usexvidmode DECLSPEC_HIDDEN; ++extern BOOL ximInComposeMode DECLSPEC_HIDDEN; ++extern BOOL use_take_focus DECLSPEC_HIDDEN; ++extern BOOL use_primary_selection DECLSPEC_HIDDEN; ++extern BOOL use_system_cursors DECLSPEC_HIDDEN; ++extern BOOL show_systray DECLSPEC_HIDDEN; ++extern BOOL grab_pointer DECLSPEC_HIDDEN; ++extern BOOL grab_fullscreen DECLSPEC_HIDDEN; ++extern BOOL usexcomposite DECLSPEC_HIDDEN; ++extern BOOL managed_mode DECLSPEC_HIDDEN; ++extern BOOL decorated_mode DECLSPEC_HIDDEN; ++extern BOOL private_color_map DECLSPEC_HIDDEN; ++extern int primary_monitor DECLSPEC_HIDDEN; ++extern int copy_default_colors DECLSPEC_HIDDEN; ++extern int alloc_system_colors DECLSPEC_HIDDEN; ++extern int xrender_error_base DECLSPEC_HIDDEN; ++extern HMODULE haikudrv_module DECLSPEC_HIDDEN; ++extern char *process_name DECLSPEC_HIDDEN; ++ ++/* X11 event driver */ ++ ++ ++static inline void mirror_rect( const RECT *window_rect, RECT *rect ) ++{ ++ int width = window_rect->right - window_rect->left; ++ int tmp = rect->left; ++ rect->left = width - rect->right; ++ rect->right = width - tmp; ++} ++ ++extern void HAIKUDRV_InitClipboard(void) DECLSPEC_HIDDEN; ++extern void CDECL HAIKUDRV_SetFocus( HWND hwnd ) DECLSPEC_HIDDEN; ++extern DWORD CDECL HAIKUDRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, ++ DWORD mask, DWORD flags ) DECLSPEC_HIDDEN; ++ ++#define DEPTH_COUNT 3 ++extern const unsigned int *depths DECLSPEC_HIDDEN; ++ ++/* Required functions for changing and enumerating display settings */ ++struct haikudrv_settings_handler ++{ ++ /* A name to tell what host driver is used */ ++ const char *name; ++ ++ /* Higher priority can override handlers with a lower priority */ ++ UINT priority; ++ ++ /* get_id() will be called to map a device name, e.g., \\.\DISPLAY1 to a driver specific id. ++ * Following functions use this id to identify the device. ++ * ++ * Return FALSE if the device cannot be found and TRUE on success */ ++ BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id); ++ ++ /* get_modes() will be called to get a list of supported modes of the device of id in modes ++ * with respect to flags, which could be 0, EDS_RAWMODE or EDS_ROTATEDMODE. If the implementation ++ * uses dmDriverExtra then every DEVMODEW in the list must have the same dmDriverExtra value ++ * ++ * Following fields in DEVMODE must be valid: ++ * dmSize, dmDriverExtra, dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight, ++ * dmDisplayFlags and dmDisplayFrequency ++ * ++ * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ ++ BOOL (*get_modes)(ULONG_PTR id, DWORD flags, DEVMODEW **modes, UINT *mode_count); ++ ++ /* free_modes() will be called to free the mode list returned from get_modes() */ ++ void (*free_modes)(DEVMODEW *modes); ++ ++ /* get_current_mode() will be called to get the current display mode of the device of id ++ * ++ * Following fields in DEVMODE must be valid: ++ * dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight, dmDisplayFlags, ++ * dmDisplayFrequency and dmPosition ++ * ++ * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */ ++ BOOL (*get_current_mode)(ULONG_PTR id, DEVMODEW *mode); ++ ++ /* set_current_mode() will be called to change the display mode of the display device of id. ++ * mode must be a valid mode from get_modes() with optional fields, such as dmPosition set. ++ * ++ * Return DISP_CHANGE_*, same as ChangeDisplaySettingsExW() return values */ ++ LONG (*set_current_mode)(ULONG_PTR id, DEVMODEW *mode); ++}; ++ ++extern void HAIKUDRV_Settings_SetHandler(const struct haikudrv_settings_handler *handler) DECLSPEC_HIDDEN; ++ ++extern void HAIKUDRV_resize_desktop(BOOL) DECLSPEC_HIDDEN; ++void HAIKUDRV_Settings_Init(void) DECLSPEC_HIDDEN; ++ ++void HAIKUDRV_XF86VM_Init(void) DECLSPEC_HIDDEN; ++void HAIKUDRV_XRandR_Init(void) DECLSPEC_HIDDEN; ++void init_user_driver(void) DECLSPEC_HIDDEN; ++ ++/* X11 display device handler. Used to initialize display device registry data */ ++ ++/* Required functions for display device registry initialization */ ++struct haikudrv_display_device_handler ++{ ++ /* A name to tell what host driver is used */ ++ const char *name; ++ ++ /* Higher priority can override handlers with lower priority */ ++ INT priority; ++ ++ /* get_gpus will be called to get a list of GPUs. First GPU has to be where the primary adapter is. ++ * ++ * Return FALSE on failure with parameters unchanged */ ++ BOOL (*get_gpus)(struct gdi_gpu **gpus, int *count); ++ ++ /* get_adapters will be called to get a list of adapters in EnumDisplayDevices context under a GPU. ++ * The first adapter has to be primary if GPU is primary. ++ * ++ * Return FALSE on failure with parameters unchanged */ ++ BOOL (*get_adapters)(ULONG_PTR gpu_id, struct gdi_adapter **adapters, int *count); ++ ++ /* get_monitors will be called to get a list of monitors in EnumDisplayDevices context under an adapter. ++ * The first monitor has to be primary if adapter is primary. ++ * ++ * Return FALSE on failure with parameters unchanged */ ++ BOOL (*get_monitors)(ULONG_PTR adapter_id, struct gdi_monitor **monitors, int *count); ++ ++ /* free_gpus will be called to free a GPU list from get_gpus */ ++ void (*free_gpus)(struct gdi_gpu *gpus); ++ ++ /* free_adapters will be called to free an adapter list from get_adapters */ ++ void (*free_adapters)(struct gdi_adapter *adapters); ++ ++ /* free_monitors will be called to free a monitor list from get_monitors */ ++ void (*free_monitors)(struct gdi_monitor *monitors, int count); ++ ++ /* register_event_handlers will be called to register event handlers. ++ * This function pointer is optional and can be NULL when driver doesn't support it */ ++ void (*register_event_handlers)(void); ++}; ++ ++extern HANDLE get_display_device_init_mutex(void) DECLSPEC_HIDDEN; ++extern BOOL get_host_primary_gpu(struct gdi_gpu *gpu) DECLSPEC_HIDDEN; ++extern void release_display_device_init_mutex(HANDLE) DECLSPEC_HIDDEN; ++extern void HAIKUDRV_DisplayDevices_SetHandler(const struct haikudrv_display_device_handler *handler) DECLSPEC_HIDDEN; ++extern void HAIKUDRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN; ++extern void HAIKUDRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN; ++extern void HAIKUDRV_DisplayDevices_Update(BOOL) DECLSPEC_HIDDEN; ++/* Display device handler used in virtual desktop mode */ ++extern struct haikudrv_display_device_handler desktop_handler DECLSPEC_HIDDEN; ++ ++ ++extern const struct user_driver_funcs haikudrv_funcs; ++ ++ ++extern BOOL HaikuStartApplication(void); ++ ++#endif /* __WINE_HAIKUDRV_H */ +diff --git a/dlls/winehaiku.drv/haikudrv_main.c b/dlls/winehaiku.drv/haikudrv_main.c +new file mode 100644 +index 00000000000..031f6d95a76 +--- /dev/null ++++ b/dlls/winehaiku.drv/haikudrv_main.c +@@ -0,0 +1,109 @@ ++/* ++ * HAIKUDRV initialization code ++ * ++ * Copyright 1998 Patrik Stridvall ++ * Copyright 2000 Alexandre Julliard ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_SYS_TIME_H ++# include ++#endif ++#ifdef HAVE_UNISTD_H ++# include ++#endif ++ ++#include "ntstatus.h" ++#define WIN32_NO_STATUS ++#include "windef.h" ++#include "winbase.h" ++#include "winreg.h" ++ ++#include "haikudrv.h" ++#include "wine/server.h" ++#include "wine/unicode.h" ++#include "wine/debug.h" ++#include "wine/list.h" ++#include "wine/heap.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++WINE_DECLARE_DEBUG_CHANNEL(synchronous); ++WINE_DECLARE_DEBUG_CHANNEL(winediag); ++ ++DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES; ++ ++ ++/*********************************************************************** ++ * HAIKUDRV process initialisation routine ++ */ ++static BOOL process_attach(void) ++{ ++ if (!HaikuStartApplication()) return FALSE; ++ if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; ++ init_user_driver(); ++ return TRUE; ++} ++ ++ ++/*********************************************************************** ++ * HAIKUDRV initialisation routine ++ */ ++BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) ++{ ++ BOOL ret = TRUE; ++ ++ switch(reason) ++ { ++ case DLL_PROCESS_ATTACH: ++ DisableThreadLibraryCalls( hinst ); ++ ret = process_attach(); ++ break; ++ } ++ return ret; ++} ++ ++ ++/*********************************************************************** ++ * SystemParametersInfo (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags ) ++{ ++ return FALSE; /* let user32 handle it */ ++} ++ ++/********************************************************************** ++ * HAIKUDRV_D3DKMTSetVidPnSourceOwner ++ */ ++NTSTATUS CDECL HAIKUDRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc ) ++{ ++ NTSTATUS status = STATUS_SUCCESS; ++ return status; ++} ++ ++/********************************************************************** ++ * HAIKUDRV_D3DKMTCheckVidPnExclusiveOwnership ++ */ ++NTSTATUS CDECL HAIKUDRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc ) ++{ ++ return STATUS_SUCCESS; ++} +diff --git a/dlls/winehaiku.drv/ime.c b/dlls/winehaiku.drv/ime.c +new file mode 100644 +index 00000000000..beb8d7c29e3 +--- /dev/null ++++ b/dlls/winehaiku.drv/ime.c +@@ -0,0 +1,181 @@ ++/* ++ * The IME for interfacing with XIM ++ * ++ * Copyright 2008 CodeWeavers, Aric Stewart ++ * ++ * 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 ++ */ ++ ++/* ++ * Notes: ++ * The normal flow for IMM/IME Processing is as follows. ++ * 1) The Keyboard Driver generates key messages which are first passed to ++ * the IMM and then to IME via ImeProcessKey. If the IME returns 0 then ++ * it does not want the key and the keyboard driver then generates the ++ * WM_KEYUP/WM_KEYDOWN messages. However if the IME is going to process the ++ * key it returns non-zero. ++ * 2) If the IME is going to process the key then the IMM calls ImeToAsciiEx to ++ * process the key. the IME modifies the HIMC structure to reflect the ++ * current state and generates any messages it needs the IMM to process. ++ * 3) IMM checks the messages and send them to the application in question. From ++ * here the IMM level deals with if the application is IME aware or not. ++ * ++ * This flow does not work well for the X11 driver and XIM. ++ * (It works fine for Mac) ++ * As such we will have to reroute step 1. Instead the haikudrv driver will ++ * generate an XIM events and call directly into this IME implementation. ++ * As such we will have to use the alternative ImmGenerateMessage path to be ++ * generate the messages that we want the IMM layer to send to the application. ++ */ ++ ++#include "config.h" ++ ++#include ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "winerror.h" ++#include "wine/debug.h" ++#include "imm.h" ++#include "ddk/imm.h" ++#include "winnls.h" ++#include "haikudrv.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(imm); ++ ++ ++BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass, ++ LPCWSTR lpszOption) ++{ ++ return TRUE; ++} ++ ++BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData) ++{ ++ FIXME("(%p, %p, %d, %p): stub\n", hKL, hWnd, dwMode, lpData); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return FALSE; ++} ++ ++DWORD WINAPI ImeConversionList(HIMC hIMC, LPCWSTR lpSource, ++ LPCANDIDATELIST lpCandList, DWORD dwBufLen, UINT uFlag) ++ ++{ ++ FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC, debugstr_w(lpSource), ++ lpCandList, dwBufLen, uFlag); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return 0; ++} ++ ++BOOL WINAPI ImeDestroy(UINT uForce) ++{ ++ return TRUE; ++} ++ ++LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData) ++{ ++ FIXME("(%p, %d, %p): stub\n", hIMC, uSubFunc, lpData); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return 0; ++} ++ ++BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) ++{ ++ /* See the comment at the head of this file */ ++ TRACE("We do no processing via this route\n"); ++ return FALSE; ++} ++ ++BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) ++{ ++ return TRUE; ++} ++ ++BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag) ++{ ++ static int once; ++ ++ if (!once++) ++ FIXME("(%p, %x): stub\n", hIMC, fFlag); ++ return TRUE; ++} ++ ++UINT WINAPI ImeToAsciiEx (UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, ++ LPDWORD lpdwTransKey, UINT fuState, HIMC hIMC) ++{ ++ /* See the comment at the head of this file */ ++ TRACE("We do no processing via this route\n"); ++ return 0; ++} ++ ++BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) ++{ ++ return FALSE; ++} ++ ++BOOL WINAPI ImeRegisterWord(LPCWSTR lpszReading, DWORD dwStyle, ++ LPCWSTR lpszRegister) ++{ ++ FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle, ++ debugstr_w(lpszRegister)); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return FALSE; ++} ++ ++BOOL WINAPI ImeUnregisterWord(LPCWSTR lpszReading, DWORD dwStyle, ++ LPCWSTR lpszUnregister) ++{ ++ FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle, ++ debugstr_w(lpszUnregister)); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return FALSE; ++} ++ ++UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUFW lpStyleBuf) ++{ ++ FIXME("(%d, %p): stub\n", nItem, lpStyleBuf); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return 0; ++} ++ ++UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc, ++ LPCWSTR lpszReading, DWORD dwStyle, ++ LPCWSTR lpszRegister, LPVOID lpData) ++{ ++ FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc, ++ debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), ++ lpData); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return 0; ++} ++ ++BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, ++ DWORD dwCompLen, LPCVOID lpRead, ++ DWORD dwReadLen) ++{ ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return FALSE; ++} ++ ++DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType, ++ LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, ++ DWORD dwSize) ++{ ++ FIXME("(%p, %x %x %p %p %x): stub\n", hIMC, dwFlags, dwType, ++ lpImeParentMenu, lpImeMenu, dwSize); ++ SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ++ return 0; ++} +diff --git a/dlls/winehaiku.drv/init.c b/dlls/winehaiku.drv/init.c +new file mode 100644 +index 00000000000..a0a279b9837 +--- /dev/null ++++ b/dlls/winehaiku.drv/init.c +@@ -0,0 +1,103 @@ ++/* ++ * Haiku graphics driver initialisation functions ++ * ++ * Copyright 1996 Alexandre Julliard ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++#include "haikudrv.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++ ++ ++#define GDI_HOOK(name) .dc_funcs.p##name = HAIKUDRV_##name ++#define GDI_WINE_HOOK(name) .dc_funcs.name = HAIKUDRV_##name ++#define USER_HOOK(name) .p##name = HAIKUDRV_##name ++const struct user_driver_funcs haikudrv_funcs = ++{ ++ GDI_HOOK(CreateCompatibleDC), ++ GDI_HOOK(CreateDC), ++ GDI_HOOK(DeleteDC), ++ GDI_HOOK(GetDeviceCaps), ++// GDI_HOOK(GetDeviceGammaRamp), ++// GDI_HOOK(SetDeviceGammaRamp), ++// GDI_WINE_HOOK(wine_get_wgl_driver), ++ GDI_WINE_HOOK(wine_get_vulkan_driver), ++ .dc_funcs.priority = GDI_PRIORITY_GRAPHICS_DRV, ++ ++ /* keyboard functions */ ++ USER_HOOK(ActivateKeyboardLayout), ++ USER_HOOK(Beep), ++ USER_HOOK(GetKeyNameText), ++ USER_HOOK(MapVirtualKeyEx), ++ USER_HOOK(ToUnicodeEx), ++ USER_HOOK(VkKeyScanEx), ++ ++ /* cursor/icon functions */ ++ USER_HOOK(DestroyCursorIcon), ++ USER_HOOK(SetCursor), ++ USER_HOOK(GetCursorPos), ++ USER_HOOK(SetCursorPos), ++ USER_HOOK(ClipCursor), ++ ++ /* clipboard functions */ ++ USER_HOOK(UpdateClipboard), ++ ++ /* display modes */ ++ USER_HOOK(ChangeDisplaySettingsEx), ++ USER_HOOK(EnumDisplaySettingsEx), ++ USER_HOOK(UpdateDisplayDevices), ++ ++ /* windowing functions */ ++ USER_HOOK(CreateDesktopWindow), ++ USER_HOOK(CreateWindow), ++ USER_HOOK(DestroyWindow), ++ USER_HOOK(FlashWindowEx), ++// USER_HOOK(GetDC), ++// USER_HOOK(MsgWaitForMultipleObjectsEx), ++// USER_HOOK(ReleaseDC), ++// USER_HOOK(ScrollDC), ++ USER_HOOK(SetCapture), ++ USER_HOOK(SetFocus), ++ USER_HOOK(SetLayeredWindowAttributes), ++ USER_HOOK(SetParent), ++ USER_HOOK(SetWindowIcon), ++ USER_HOOK(SetWindowRgn), ++ USER_HOOK(SetWindowStyle), ++ USER_HOOK(SetWindowText), ++ USER_HOOK(ShowWindow), ++ USER_HOOK(SysCommand), ++ USER_HOOK(UpdateLayeredWindow), ++ USER_HOOK(WindowMessage), ++ USER_HOOK(WindowPosChanging), ++ USER_HOOK(WindowPosChanged), ++ ++ /* system parameters */ ++ USER_HOOK(SystemParametersInfo), ++ ++ /* thread management */ ++ USER_HOOK(ThreadDetach), ++}; ++#undef GDI_HOOK ++#undef GDI_WINE_HOOK ++#undef USER_HOOK ++ ++void init_user_driver(void) ++{ ++ __wine_set_user_driver(&haikudrv_funcs, WINE_GDI_DRIVER_VERSION); ++} +diff --git a/dlls/winehaiku.drv/keyboard.c b/dlls/winehaiku.drv/keyboard.c +new file mode 100644 +index 00000000000..007004f4924 +--- /dev/null ++++ b/dlls/winehaiku.drv/keyboard.c +@@ -0,0 +1,92 @@ ++/* ++ * X11 keyboard driver ++ * ++ * Copyright 1993 Bob Amstadt ++ * Copyright 1996 Albrecht Kleine ++ * Copyright 1997 David Faure ++ * Copyright 1998 Morten Welinder ++ * Copyright 1998 Ulrich Weigand ++ * Copyright 1999 Ove Kåven ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#define NONAMELESSUNION ++ ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "winreg.h" ++#include "winnls.h" ++#include "ime.h" ++#include "haikudrv.h" ++#include "wine/server.h" ++#include "wine/unicode.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(keyboard); ++WINE_DECLARE_DEBUG_CHANNEL(key); ++ ++ ++/*********************************************************************** ++ * ActivateKeyboardLayout (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_ActivateKeyboardLayout(HKL hkl, UINT flags) ++{ ++ return TRUE; ++} ++ ++ ++/*********************************************************************** ++ * VkKeyScanEx (HAIKUDRV.@) ++ * ++ * Note: Windows ignores HKL parameter and uses current active layout instead ++ */ ++SHORT CDECL HAIKUDRV_VkKeyScanEx(WCHAR wChar, HKL hkl) ++{ ++ //FIXME("(%u): stub\n", wChar); ++ return 0; ++} ++ ++/*********************************************************************** ++ * MapVirtualKeyEx (HAIKUDRV.@) ++ */ ++UINT CDECL HAIKUDRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) ++{ ++ //FIXME("(%u): stub\n", wCode); ++ return 0; ++} ++ ++/*********************************************************************** ++ * GetKeyNameText (HAIKUDRV.@) ++ */ ++INT CDECL HAIKUDRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize) ++{ ++ return 0; ++} ++ ++/*********************************************************************** ++ * Beep (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_Beep(void) ++{ ++} +diff --git a/dlls/winehaiku.drv/mouse.c b/dlls/winehaiku.drv/mouse.c +new file mode 100644 +index 00000000000..b44039e9d76 +--- /dev/null ++++ b/dlls/winehaiku.drv/mouse.c +@@ -0,0 +1,79 @@ ++/* ++ * X11 mouse driver ++ * ++ * Copyright 1998 Ulrich Weigand ++ * Copyright 2007 Henri Verbeet ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++ ++#define NONAMELESSUNION ++#define OEMRESOURCE ++#include "windef.h" ++#include "winbase.h" ++#include "winreg.h" ++ ++#include "haikudrv.h" ++#include "wine/server.h" ++#include "wine/unicode.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(cursor); ++ ++ ++/*********************************************************************** ++ * DestroyCursorIcon (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_DestroyCursorIcon( HCURSOR handle ) ++{ ++} ++ ++/*********************************************************************** ++ * SetCursor (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_SetCursor( HCURSOR handle ) ++{ ++} ++ ++/*********************************************************************** ++ * SetCursorPos (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_SetCursorPos( INT x, INT y ) ++{ ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * GetCursorPos (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_GetCursorPos(LPPOINT pos) ++{ ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * ClipCursor (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_ClipCursor( LPCRECT clip ) ++{ ++ return TRUE; ++} +diff --git a/dlls/winehaiku.drv/settings.cpp b/dlls/winehaiku.drv/settings.cpp +new file mode 100644 +index 00000000000..967ae928b6f +--- /dev/null ++++ b/dlls/winehaiku.drv/settings.cpp +@@ -0,0 +1,74 @@ ++/* ++ * Wine X11drv display settings functions ++ * ++ * Copyright 2003 Alexander James Pasadyn ++ * Copyright 2020 Zhiyi Zhang for CodeWeavers ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++#include ++ ++#define NONAMELESSUNION ++#define NONAMELESSSTRUCT ++ ++extern "C" { ++#include "haikudrv.h" ++ ++#include "windef.h" ++#include "winreg.h" ++#include "wingdi.h" ++#include "wine/debug.h" ++#include "wine/heap.h" ++#include "wine/unicode.h" ++} ++ ++WINE_DEFAULT_DEBUG_CHANNEL(x11settings); ++ ++ ++/*********************************************************************** ++ * EnumDisplaySettingsEx (HAIKUDRV.@) ++ * ++ */ ++BOOL CDECL HAIKUDRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags) ++{ ++ switch (n) { ++ case ENUM_REGISTRY_SETTINGS: ++ case ENUM_CURRENT_SETTINGS: ++ case 0: { ++ devmode->u1.s2.dmPosition.x = 0; ++ devmode->u1.s2.dmPosition.y = 0; ++ devmode->dmPelsWidth = 1920; ++ devmode->dmPelsHeight = 1080; ++ devmode->dmDisplayFrequency = 60; ++ devmode->dmBitsPerPel = 32; ++ devmode->u1.s2.dmDisplayOrientation = 0; ++ return TRUE; ++ } ++ default:; ++ } ++ return FALSE; ++} ++ ++/*********************************************************************** ++ * ChangeDisplaySettingsEx (HAIKUDRV.@) ++ * ++ */ ++LONG CDECL HAIKUDRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, ++ HWND hwnd, DWORD flags, LPVOID lpvoid ) ++{ ++ return 0; ++} +diff --git a/dlls/winehaiku.drv/systray.c b/dlls/winehaiku.drv/systray.c +new file mode 100644 +index 00000000000..a6ee21766c0 +--- /dev/null ++++ b/dlls/winehaiku.drv/systray.c +@@ -0,0 +1,74 @@ ++/* ++ * X11 system tray management ++ * ++ * Copyright (C) 2004 Mike Hearn, for CodeWeavers ++ * Copyright (C) 2005 Robert Shearman ++ * Copyright (C) 2008 Alexandre Julliard ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#ifdef HAVE_UNISTD_H ++# include ++#endif ++ ++#define NONAMELESSUNION ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "commctrl.h" ++#include "shellapi.h" ++ ++#include "haikudrv.h" ++#include "wine/list.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(systray); ++ ++ ++/*********************************************************************** ++ * wine_notify_icon (HAIKUDRV.@) ++ * ++ * Driver-side implementation of Shell_NotifyIcon. ++ */ ++int CDECL wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data ) ++{ ++ BOOL ret = FALSE; ++ ++ switch (msg) ++ { ++ case NIM_ADD: ++ break; ++ case NIM_DELETE: ++ break; ++ case NIM_MODIFY: ++ break; ++ case NIM_SETVERSION: ++ break; ++ case 0xdead: /* Wine extension: owner window has died */ ++ break; ++ default: ++ FIXME( "unhandled tray message: %u\n", msg ); ++ break; ++ } ++ return ret; ++} +diff --git a/dlls/winehaiku.drv/version.rc b/dlls/winehaiku.drv/version.rc +new file mode 100644 +index 00000000000..56c62174719 +--- /dev/null ++++ b/dlls/winehaiku.drv/version.rc +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (c) 2007 Alexandre Julliard ++ * ++ * 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 ++ */ ++ ++#define WINE_FILEDESCRIPTION_STR "Wine X11 driver" ++#define WINE_FILENAME_STR "winex11.drv" ++ ++#include "wine/wine_common_ver.rc" +diff --git a/dlls/winehaiku.drv/vidmode.c b/dlls/winehaiku.drv/vidmode.c +new file mode 100644 +index 00000000000..0930257d57b +--- /dev/null ++++ b/dlls/winehaiku.drv/vidmode.c +@@ -0,0 +1,57 @@ ++/* ++ * DirectDraw XVidMode interface ++ * ++ * Copyright 2001 TransGaming Technologies, Inc. ++ * Copyright 2020 Zhiyi Zhang for CodeWeavers ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define NONAMELESSSTRUCT ++#define NONAMELESSUNION ++ ++#include "haikudrv.h" ++ ++#include "windef.h" ++#include "wingdi.h" ++#include "wine/debug.h" ++#include "wine/heap.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(vidmode); ++ ++ ++/*********************************************************************** ++ * GetDeviceGammaRamp (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_GetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) ++{ ++ return FALSE; ++} ++ ++/*********************************************************************** ++ * SetDeviceGammaRamp (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_SetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) ++{ ++ return FALSE; ++} +diff --git a/dlls/winehaiku.drv/vulkan.cpp b/dlls/winehaiku.drv/vulkan.cpp +new file mode 100644 +index 00000000000..32929122ff7 +--- /dev/null ++++ b/dlls/winehaiku.drv/vulkan.cpp +@@ -0,0 +1,418 @@ ++extern "C" { ++#include "config.h" ++#include "haikudrv.h" ++#include "wine/heap.h" ++#include "wine/debug.h" ++ ++#define WINE_VK_HOST ++ ++#include "wine/vulkan.h" ++#include "wine/vulkan_driver.h" ++} ++#include ++ ++WINE_DEFAULT_DEBUG_CHANNEL(vulkan); ++ ++ ++#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" ++typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; ++typedef struct VkHeadlessSurfaceCreateInfoEXT { ++ VkStructureType sType; ++ const void* pNext; ++ VkHeadlessSurfaceCreateFlagsEXT flags; ++} VkHeadlessSurfaceCreateInfoEXT; ++ ++enum { ++ VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000 ++}; ++ ++typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); ++ ++ ++static void *haikudrv_get_vk_device_proc_addr(const char *name); ++static void *haikudrv_get_vk_instance_proc_addr(VkInstance instance, const char *name); ++ ++ ++static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, ++ VkInstanceCreateInfo *dst) ++{ ++ unsigned int i; ++ const char **enabled_extensions = NULL; ++ ++ dst->sType = src->sType; ++ dst->flags = src->flags; ++ dst->pApplicationInfo = src->pApplicationInfo; ++ dst->pNext = src->pNext; ++ dst->enabledLayerCount = 0; ++ dst->ppEnabledLayerNames = NULL; ++ dst->enabledExtensionCount = 0; ++ dst->ppEnabledExtensionNames = NULL; ++ ++ TRACE("sType: %d\n", dst->sType); ++ TRACE("dst->flags: %d\n", dst->flags); ++ TRACE("dst->pApplicationInfo->sType: %d\n", dst->pApplicationInfo->sType); ++ TRACE("dst->pApplicationInfo->pApplicationName: \"%s\"\n", dst->pApplicationInfo->pApplicationName); ++ TRACE("dst->pApplicationInfo->pEngineName: \"%s\"\n", dst->pApplicationInfo->pEngineName); ++ TRACE("dst->pApplicationInfo->apiVersion: %d\n", dst->pApplicationInfo->apiVersion); ++ TRACE("dst->pNext: %p\n", dst->pNext); ++ ((VkApplicationInfo*)dst->pApplicationInfo)->apiVersion = 4194304; ++/* ++ enabled_extensions = heap_calloc(2, sizeof(*src->ppEnabledExtensionNames)); ++ enabled_extensions[0] = "VK_KHR_surface"; ++ enabled_extensions[1] = "VK_EXT_headless_surface"; ++ dst->ppEnabledExtensionNames = enabled_extensions; ++ dst->enabledExtensionCount = 2; ++ return VK_SUCCESS; ++*/ ++ if (src->enabledExtensionCount > 0) ++ { ++ enabled_extensions = (const char**)heap_calloc(src->enabledExtensionCount, sizeof(*src->ppEnabledExtensionNames)); ++ if (!enabled_extensions) ++ { ++ ERR("Failed to allocate memory for enabled extensions\n"); ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ } ++ ++ for (i = 0; i < src->enabledExtensionCount; i++) ++ { ++ if ( ++ !strcmp(src->ppEnabledExtensionNames[i], "VK_KHR_win32_surface") ++ ) ++ { ++ enabled_extensions[i] = "VK_EXT_headless_surface"; ++ } ++ else ++ { ++ enabled_extensions[i] = src->ppEnabledExtensionNames[i]; ++ } ++ TRACE("enabled_extensions[%d]: \"%s\"\n", i, enabled_extensions[i]); ++ } ++ dst->ppEnabledExtensionNames = enabled_extensions; ++ dst->enabledExtensionCount = src->enabledExtensionCount; ++ } ++ ++ return VK_SUCCESS; ++} ++ ++static const char *wine_vk_native_fn_name(const char *name) ++{ ++ if (strcmp(name, "vkCreateWin32SurfaceKHR") == 0) { ++ return "vkCreateHeadlessSurfaceEXT"; ++ } ++ if (strcmp(name, "vkGetPhysicalDeviceWin32PresentationSupportKHR") == 0) { ++ return "vkCreateHeadlessSurfaceEXT"; ++ } ++ return name; ++} ++ ++ ++//#pragma mark - ++ ++class VKWineSurface { ++}; ++ ++class VKWineImage { ++private: ++ VkImage fImage; ++ VkDeviceMemory fMemory; ++}; ++ ++class VKWineSwapchain { ++private: ++ ArrayDeleter fImages; ++ ++public: ++ VKWineSwapchain(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo); ++}; ++ ++ ++//#pragma mark - ++ ++static VkResult haikudrv_vkCreateInstance(const VkInstanceCreateInfo *create_info, ++ const VkAllocationCallbacks *allocator, VkInstance *instance) ++{ ++ VkInstanceCreateInfo create_info_host; ++ VkResult res; ++ TRACE("(create_info: %p, allocator: %p, instance: %p)\n", create_info, allocator, instance); ++ ++ if (allocator) ++ FIXME("Support for allocation callbacks not implemented yet\n"); ++ ++ /* Perform a second pass on converting VkInstanceCreateInfo. Winevulkan ++ * performed a first pass in which it handles everything except for WSI ++ * functionality such as VK_KHR_win32_surface. Handle this now. ++ */ ++ res = wine_vk_instance_convert_create_info(create_info, &create_info_host); ++ if (res != VK_SUCCESS) ++ { ++ ERR("Failed to convert instance create info, res=%d\n", res); ++ return res; ++ } ++ ++ res = vkCreateInstance(&create_info_host, NULL /* allocator */, instance); ++ ++ heap_free((void *)create_info_host.ppEnabledExtensionNames); ++ return res; ++} ++ ++static VkResult haikudrv_vkCreateSwapchainKHR(VkDevice device, ++ const VkSwapchainCreateInfoKHR *create_info, ++ const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain) ++{ ++ TRACE("()\n"); ++ return vkCreateSwapchainKHR(device, create_info, allocator, swapchain); ++} ++ ++static VkResult haikudrv_vkCreateWin32SurfaceKHR(VkInstance instance, ++ const VkWin32SurfaceCreateInfoKHR *create_info, ++ const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) ++{ ++ TRACE("()\n"); ++ PFN_vkCreateHeadlessSurfaceEXT proc = (PFN_vkCreateHeadlessSurfaceEXT) ++ vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"); ++ VkHeadlessSurfaceCreateInfoEXT surfaceCreateInfo = {}; ++ surfaceCreateInfo.sType = (VkStructureType)VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT; ++ return proc(instance, &surfaceCreateInfo, allocator, surface); ++} ++ ++static void haikudrv_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator) ++{ ++ TRACE("()\n"); ++ vkDestroyInstance(instance, allocator); ++} ++ ++static void haikudrv_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, ++ const VkAllocationCallbacks *allocator) ++{ ++ TRACE("()\n"); ++ vkDestroySurfaceKHR(instance, surface, allocator); ++} ++ ++static void haikudrv_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, ++ const VkAllocationCallbacks *allocator) ++{ ++ TRACE("()\n"); ++ vkDestroySwapchainKHR(device, swapchain, allocator); ++} ++ ++static VkResult haikudrv_vkEnumerateInstanceExtensionProperties(const char *layer_name, ++ uint32_t *count, VkExtensionProperties* properties) ++{ ++ unsigned int i; ++ BOOL seen_surface = FALSE; ++ VkResult res; ++ ++ TRACE("layer_name %s, count %p, properties %p\n", debugstr_a(layer_name), count, properties); ++ ++ /* This shouldn't get called with layer_name set, the ICD loader prevents it. */ ++ if (layer_name) ++ { ++ ERR("Layer enumeration not supported from ICD.\n"); ++ return VK_ERROR_LAYER_NOT_PRESENT; ++ } ++ ++ /* We will return at most the same number of instance extensions reported by the host back to ++ * winevulkan. Along the way we may replace MoltenVK extensions with their win32 equivalents, ++ * or remove redundant extensions outright. ++ * Winevulkan will perform more detailed filtering as it knows whether it has thunks ++ * for a particular extension. ++ */ ++ res = vkEnumerateInstanceExtensionProperties(layer_name, count, properties); ++ if (!properties || res < 0) ++ return res; ++ ++ for (i = 0; i < *count; i++) ++ { ++ /* For now the only MoltenVK extensions we need to fixup. Long-term we may need an array. */ ++ if (!strcmp(properties[i].extensionName, "VK_EXT_headless_surface")) ++ { ++ if (seen_surface) ++ { ++ /* If we've already seen a surface extension, just hide this one. */ ++ memmove(properties + i, properties + i + 1, (*count - i - 1) * sizeof(*properties)); ++ --*count; ++ --i; ++ continue; ++ } ++ TRACE("Substituting %s for VK_KHR_win32_surface\n", properties[i].extensionName); ++ ++ snprintf(properties[i].extensionName, sizeof(properties[i].extensionName), ++ VK_KHR_WIN32_SURFACE_EXTENSION_NAME); ++ properties[i].specVersion = VK_KHR_WIN32_SURFACE_SPEC_VERSION; ++ seen_surface = TRUE; ++ } ++ } ++ ++ TRACE("Returning %u extensions.\n", *count); ++ return res; ++} ++ ++static void *haikudrv_vkGetDeviceProcAddr(VkDevice device, const char *name) ++{ ++ void *proc_addr; ++ ++ TRACE("(%p, %s)\n", device, debugstr_a(name)); ++ ++ if (!vkGetDeviceProcAddr(device, wine_vk_native_fn_name(name))) { ++ ERR("%s not found\n", debugstr_a(name)); ++ return NULL; ++ } ++ ++ if ((proc_addr = haikudrv_get_vk_device_proc_addr(name))) ++ return proc_addr; ++ ++ return (void*)vkGetDeviceProcAddr(device, name); ++} ++ ++static void *haikudrv_vkGetInstanceProcAddr(VkInstance instance, const char *name) ++{ ++ void *proc_addr; ++ ++ TRACE("(%p, %s)\n", instance, debugstr_a(name)); ++ ++ if (!vkGetInstanceProcAddr(instance, wine_vk_native_fn_name(name))) { ++ ERR("%s not found\n", debugstr_a(name)); ++ return NULL; ++ } ++ ++ if ((proc_addr = haikudrv_get_vk_instance_proc_addr(instance, name))) ++ return proc_addr; ++ ++ return (void*)vkGetInstanceProcAddr(instance, name); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev, ++ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, surface_info, capabilities); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev, ++ VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface, capabilities); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev, ++ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, uint32_t *count, VkSurfaceFormat2KHR *formats) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, surface_info, count, formats); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, ++ VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface, count, formats); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev, ++ VkSurfaceKHR surface, uint32_t *count, VkPresentModeKHR *modes) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev, surface, count, modes); ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev, ++ uint32_t index, VkSurfaceKHR surface, VkBool32 *supported) ++{ ++ TRACE("()\n"); ++ return vkGetPhysicalDeviceSurfaceSupportKHR(phys_dev, index, surface, supported); ++} ++ ++static VkBool32 haikudrv_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, ++ uint32_t index) ++{ ++ TRACE("()\n"); ++ return VK_TRUE; ++} ++ ++static VkResult haikudrv_vkGetSwapchainImagesKHR(VkDevice device, ++ VkSwapchainKHR swapchain, uint32_t *count, VkImage *images) ++{ ++ TRACE("()\n"); ++ return vkGetSwapchainImagesKHR(device, swapchain, count, images); ++} ++ ++static VkResult haikudrv_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info) ++{ ++ TRACE("()\n"); ++ return vkQueuePresentKHR(queue, present_info); ++} ++ ++static VkSurfaceKHR haikudrv_wine_get_native_surface(VkSurfaceKHR surface) ++{ ++ TRACE("0x%s\n", wine_dbgstr_longlong(surface)); ++ return surface; ++} ++ ++ ++#define VULKAN_HOOK(name) .p_##name = haikudrv_##name ++static const struct vulkan_funcs vulkan_funcs = ++{ ++ VULKAN_HOOK(vkCreateInstance), ++ VULKAN_HOOK(vkCreateSwapchainKHR), ++ VULKAN_HOOK(vkCreateWin32SurfaceKHR), ++ VULKAN_HOOK(vkDestroyInstance), ++ VULKAN_HOOK(vkDestroySurfaceKHR), ++ VULKAN_HOOK(vkDestroySwapchainKHR), ++ VULKAN_HOOK(vkEnumerateInstanceExtensionProperties), ++ // vkGetDeviceGroupSurfacePresentModesKHR ++ VULKAN_HOOK(vkGetDeviceProcAddr), ++ VULKAN_HOOK(vkGetInstanceProcAddr), ++ // vkGetPhysicalDevicePresentRectanglesKHR ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfaceCapabilities2KHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfaceFormats2KHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfaceFormatsKHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfacePresentModesKHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceSurfaceSupportKHR), ++ VULKAN_HOOK(vkGetPhysicalDeviceWin32PresentationSupportKHR), ++ VULKAN_HOOK(vkGetSwapchainImagesKHR), ++ VULKAN_HOOK(vkQueuePresentKHR), ++ ++ VULKAN_HOOK(wine_get_native_surface) ++}; ++#undef VULKAN_HOOK ++ ++static void *haikudrv_get_vk_device_proc_addr(const char *name) ++{ ++ TRACE("(\"%s\")\n", name); ++ return get_vulkan_driver_device_proc_addr(&vulkan_funcs, name); ++} ++ ++static void *haikudrv_get_vk_instance_proc_addr(VkInstance instance, const char *name) ++{ ++ TRACE("(\"%s\")\n", name); ++ return get_vulkan_driver_instance_proc_addr(&vulkan_funcs, instance, name); ++} ++ ++ ++static const struct vulkan_funcs *get_vulkan_driver(UINT version) ++{ ++ TRACE("()\n"); ++ if (version != WINE_VULKAN_DRIVER_VERSION) ++ { ++ ERR("version mismatch, vulkan wants %u but driver has %u\n", version, WINE_VULKAN_DRIVER_VERSION); ++ return NULL; ++ } ++ ++ return &vulkan_funcs; ++} ++ ++ ++const struct vulkan_funcs *CDECL HAIKUDRV_wine_get_vulkan_driver(PHYSDEV dev, UINT version) ++{ ++ TRACE("()\n"); ++ const struct vulkan_funcs *ret; ++ ++ if (!(ret = get_vulkan_driver( version ))) ++ { ++ dev = GET_NEXT_PHYSDEV( dev, wine_get_vulkan_driver ); ++ ret = dev->funcs->wine_get_vulkan_driver( dev, version ); ++ } ++ return ret; ++} +diff --git a/dlls/winehaiku.drv/window.cpp b/dlls/winehaiku.drv/window.cpp +new file mode 100644 +index 00000000000..26667b2ad0c +--- /dev/null ++++ b/dlls/winehaiku.drv/window.cpp +@@ -0,0 +1,1393 @@ ++/* ++ * Window related functions ++ * ++ * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard ++ * Copyright 1993 David Metcalfe ++ * Copyright 1995, 1996 Alex Korobka ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#ifdef HAVE_UNISTD_H ++# include ++#endif ++ ++#define thread_info haiku_thread_info ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#undef thread_info ++ ++#include ++ ++ ++/* avoid conflict with field names in included win32 headers */ ++#undef Status ++#include "windef.h" ++#include "winbase.h" ++#include "wingdi.h" ++#include "winuser.h" ++#include "wine/unicode.h" ++ ++extern "C" { ++#include "haikudrv.h" ++#include "wine/debug.h" ++#include "wine/server.h" ++} ++ ++#undef SendMessage ++ ++WINE_DEFAULT_DEBUG_CHANNEL(haikudrv); ++ ++static HWND sCaptureWnd = NULL; ++ ++enum { ++ windowResizedMsg = 1, ++}; ++ ++ ++//#pragma mark - ++ ++struct haikudrv_thread_data { ++}; ++ ++ ++static WORD sVkFromHaikuKeycodes[256]; ++static WORD sScanFromHaikuKeycodes[256]; ++static uint8 sHaikuFromVkKeycodes[256]; ++static key_map *sHaikuKeymap = NULL; // TODO: call free() on exit ++static char *sHaikuKeymapChars = NULL; // TODO: call free() on exit ++ ++ ++static void WriteSet(uint32 val) ++{ ++ printf("{"); ++ bool first = true; ++ for (uint32 i = 0; i < 32; i++) { ++ if ((1 << i) & val) { ++ if (first) first = false; else printf(", "); ++ printf("%" B_PRIu32, i); ++ } ++ } ++ printf("}"); ++} ++ ++ ++static void FromHaikuKeyCode(WORD &vkey, WORD &scan, int32 key) ++{ ++ switch (key) { ++ case 0x01: vkey = VK_ESCAPE; scan = 0x01; break; ++ case 0x02: vkey = VK_F1; scan = 0x3b; break; ++ case 0x03: vkey = VK_F2; scan = 0x3c; break; ++ case 0x04: vkey = VK_F3; scan = 0x3d; break; ++ case 0x05: vkey = VK_F4; scan = 0x3e; break; ++ case 0x06: vkey = VK_F5; scan = 0x3f; break; ++ case 0x07: vkey = VK_F6; scan = 0x40; break; ++ case 0x08: vkey = VK_F7; scan = 0x41; break; ++ case 0x09: vkey = VK_F8; scan = 0x42; break; ++ case 0x0a: vkey = VK_F9; scan = 0x43; break; ++ case 0x0b: vkey = VK_F10; scan = 0x44; break; ++ case 0x0c: vkey = VK_F11; scan = 0x57; break; ++ case 0x0d: vkey = VK_F12; scan = 0x58; break; ++ case 0x0e: vkey = VK_SNAPSHOT; scan = 0; break; ++ case 0x0f: vkey = VK_SCROLL; scan = 0; break; ++ ++ case 0x12: vkey = '1'; scan = 0x02; break; ++ case 0x13: vkey = '2'; scan = 0x03; break; ++ case 0x14: vkey = '3'; scan = 0x04; break; ++ case 0x15: vkey = '4'; scan = 0x05; break; ++ case 0x16: vkey = '5'; scan = 0x06; break; ++ case 0x17: vkey = '6'; scan = 0x07; break; ++ case 0x18: vkey = '7'; scan = 0x08; break; ++ case 0x19: vkey = '8'; scan = 0x09; break; ++ case 0x1a: vkey = '9'; scan = 0x0a; break; ++ case 0x1b: vkey = '0'; scan = 0x0b; break; ++ case 0x1c: vkey = VK_OEM_MINUS; scan = 0x0c; break; ++ case 0x1d: vkey = VK_OEM_7; scan = 0x0d; break; ++ case 0x1e: vkey = VK_BACK; scan = 0x0e; break; ++ case 0x1f: vkey = VK_INSERT; scan = 0; break; ++ ++ case 0x26: vkey = VK_TAB; scan = 0x0f; break; ++ case 0x27: vkey = 'Q'; scan = 0x10; break; ++ case 0x28: vkey = 'W'; scan = 0x11; break; ++ case 0x29: vkey = 'E'; scan = 0x12; break; ++ case 0x2a: vkey = 'R'; scan = 0x13; break; ++ case 0x2b: vkey = 'T'; scan = 0x14; break; ++ case 0x2c: vkey = 'Y'; scan = 0x15; break; ++ case 0x2d: vkey = 'U'; scan = 0x16; break; ++ case 0x2e: vkey = 'I'; scan = 0x17; break; ++ case 0x2f: vkey = 'O'; scan = 0x18; break; ++ case 0x30: vkey = 'P'; scan = 0x19; break; ++ case 0x31: vkey = VK_OEM_3; scan = 0; break; ++ case 0x32: vkey = VK_OEM_4; scan = 0; break; ++ case 0x33: vkey = VK_OEM_6; scan = 0; break; ++ case 0x34: vkey = VK_DELETE; scan = 0; break; ++ ++ case 0x3b: vkey = VK_CAPITAL; scan = 0x3a; break; ++ case 0x3c: vkey = 'A'; scan = 0x1e; break; ++ case 0x3d: vkey = 'S'; scan = 0x1f; break; ++ case 0x3e: vkey = 'D'; scan = 0x20; break; ++ case 0x3f: vkey = 'F'; scan = 0x21; break; ++ case 0x40: vkey = 'G'; scan = 0x22; break; ++ case 0x41: vkey = 'H'; scan = 0x23; break; ++ case 0x42: vkey = 'J'; scan = 0x24; break; ++ case 0x43: vkey = 'K'; scan = 0x25; break; ++ case 0x44: vkey = 'L'; scan = 0x26; break; ++ case 0x45: vkey = VK_OEM_PLUS; scan = 0x27; break; ++ case 0x46: vkey = VK_OEM_1; scan = 0x28; break; ++ case 0x47: vkey = VK_RETURN; scan = 0x1c; break; ++ ++ case 0x4b: vkey = VK_LSHIFT; scan = 0x2a; break; ++ case 0x4c: vkey = 'Z'; scan = 0x2c; break; ++ case 0x4d: vkey = 'X'; scan = 0x2d; break; ++ case 0x4e: vkey = 'C'; scan = 0x2e; break; ++ case 0x4f: vkey = 'V'; scan = 0x2f; break; ++ case 0x50: vkey = 'B'; scan = 0x30; break; ++ case 0x51: vkey = 'N'; scan = 0x31; break; ++ case 0x52: vkey = 'M'; scan = 0x32; break; ++ case 0x53: vkey = VK_OEM_COMMA; scan = 0x33; break; ++ case 0x54: vkey = VK_OEM_PERIOD; scan = 0x34; break; ++ case 0x55: vkey = VK_OEM_2; scan = 0x35; break; ++ case 0x56: vkey = VK_RSHIFT; scan = 0x36; break; ++ case 0x57: vkey = VK_UP; scan = 0; break; ++ ++ case 0x5c: vkey = VK_LCONTROL; scan = 0; break; ++ case 0x5d: vkey = VK_LMENU; scan = 0x38; break; ++ case 0x5e: vkey = VK_SPACE; scan = 0x39; break; ++ ++ case 0x61: vkey = VK_LEFT; scan = 0; break; ++ case 0x62: vkey = VK_DOWN; scan = 0; break; ++ case 0x63: vkey = VK_RIGHT; scan = 0; break; ++ ++ case 0x66: vkey = VK_LWIN; scan = 0; break; ++ case 0x68: vkey = VK_APPS; scan = 0; break; ++ ++ case 0x6a: vkey = VK_OEM_5; scan = 0; break; ++ case 0x6b: vkey = VK_OEM_102; scan = 0; break; ++ ++ default: vkey = 0; scan = 0; ++ } ++} ++ ++static void InitKeymap() ++{ ++ for (int i = 0; i < 256; i++) { ++ FromHaikuKeyCode(sVkFromHaikuKeycodes[i], sScanFromHaikuKeycodes[i], i); ++ } ++ for (int i = 0; i < 256; i++) { ++ sHaikuFromVkKeycodes[sVkFromHaikuKeycodes[i]] = i; ++ } ++ ++ get_key_map(&sHaikuKeymap, &sHaikuKeymapChars); ++} ++ ++static uint32 HaikuModifiersFromKeyState(const BYTE *lpKeyState) ++{ ++ uint32 modifiers = 0; ++ if (lpKeyState[VK_MENU ] & 0x80) modifiers |= B_COMMAND_KEY; ++ if (lpKeyState[VK_SHIFT ] & 0x80) modifiers |= B_SHIFT_KEY; ++ if (lpKeyState[VK_CONTROL] & 0x80) modifiers |= B_CONTROL_KEY; ++ if (lpKeyState[VK_LWIN ] & 0x80) modifiers |= B_OPTION_KEY; ++ if (lpKeyState[VK_NUMLOCK] & 0x01) modifiers |= B_NUM_LOCK; ++ if (lpKeyState[VK_CAPITAL] & 0x01) modifiers |= B_CAPS_LOCK; ++ if (lpKeyState[VK_SCROLL ] & 0x01) modifiers |= B_SCROLL_LOCK; ++ return modifiers; ++} ++ ++static void MapKey(char *&chars, size_t &len, int32 key, uint32 modifiers) ++{ ++ char *ch; ++ switch (modifiers & (B_SHIFT_KEY | B_CONTROL_KEY | B_OPTION_KEY | B_CAPS_LOCK)) { ++ case B_OPTION_KEY | B_CAPS_LOCK | B_SHIFT_KEY: ch = sHaikuKeymapChars + sHaikuKeymap->option_caps_shift_map[key]; break; ++ case B_OPTION_KEY | B_CAPS_LOCK: ch = sHaikuKeymapChars + sHaikuKeymap->option_caps_map[key]; break; ++ case B_OPTION_KEY | B_SHIFT_KEY: ch = sHaikuKeymapChars + sHaikuKeymap->option_shift_map[key]; break; ++ case B_OPTION_KEY: ch = sHaikuKeymapChars + sHaikuKeymap->option_map[key]; break; ++ case B_CAPS_LOCK | B_SHIFT_KEY: ch = sHaikuKeymapChars + sHaikuKeymap->caps_shift_map[key]; break; ++ case B_CAPS_LOCK: ch = sHaikuKeymapChars + sHaikuKeymap->caps_map[key]; break; ++ case B_SHIFT_KEY: ch = sHaikuKeymapChars + sHaikuKeymap->shift_map[key]; break; ++ default: ++ if (modifiers & B_CONTROL_KEY) ch = sHaikuKeymapChars + sHaikuKeymap->control_map[key]; ++ else ch = sHaikuKeymapChars + sHaikuKeymap->normal_map[key]; ++ } ++ len = *ch; ++ chars = ch + 1; ++} ++ ++ ++//#pragma mark - ++ ++class WineView: public BView { ++private: ++ HWND fHwnd; ++ struct haikudrv_thread_data *fData; ++ BBitmap *fBitmap; ++ uint32 fOldMouseBtns; ++ ++public: ++ WineView(HWND hwnd, struct haikudrv_thread_data *data, BRect frame, const char *name); ++ void UpdateBitmap(BBitmap *bitmap, BRect dirty); ++ void MessageReceived(BMessage *msg); ++ ++}; ++ ++class WineWindow: public BWindow { ++private: ++ WineView *fView; ++ HWND fHwnd; ++ struct haikudrv_thread_data *fData; ++ ++public: ++ mutex fCreateMutex; ++ window_surface *fSurface; ++ bool fSendResizeEvents; ++ bool fInDestroy; ++ RECT fNonClient; ++ //HANDLE fEvent; ++ ++ WineWindow(HWND hwnd, struct haikudrv_thread_data *data, BRect frame); ++ virtual ~WineWindow(); ++ ++ bool QuitRequested() override; ++ ++ void FrameMoved(BPoint newPosition) override; ++ void FrameResized(float newWidth, float newHeight) override; ++ ++ HWND Handle() {return fHwnd;} ++ WineView *View() {return fView;} ++}; ++ ++class WineApplication: public BApplication { ++public: ++ WineApplication(); ++}; ++ ++ ++WineView::WineView(HWND hwnd, struct haikudrv_thread_data *data, BRect frame, const char *name): ++ BView(frame, name, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE), ++ fHwnd(hwnd), ++ fData(data), ++ fBitmap(NULL), ++ fOldMouseBtns(0) ++{ ++} ++ ++void WineView::UpdateBitmap(BBitmap *bitmap, BRect dirty) ++{ ++ if (bitmap != fBitmap) { ++ fBitmap = bitmap; ++ SetViewBitmap(fBitmap, B_FOLLOW_LEFT_TOP, 0); ++ } ++ Invalidate(dirty); ++} ++ ++void WineView::MessageReceived(BMessage *msg) ++{ ++ if (sCaptureWnd != NULL && sCaptureWnd != fHwnd) { ++ return BView::MessageReceived(msg); ++ } ++ switch (msg->what) { ++ case B_KEY_DOWN: ++ case B_KEY_UP: ++ case B_UNMAPPED_KEY_DOWN: ++ case B_UNMAPPED_KEY_UP: { ++ HWND hwnd = fHwnd; ++ //msg->FindPointer("hwnd", (void**)&hwnd); ++ int32 key; ++ msg->FindInt32("key", &key); ++ ++ INPUT input; ++ input.type = INPUT_KEYBOARD; ++ input.ki.dwFlags = (msg->what == B_KEY_UP || msg->what == B_UNMAPPED_KEY_UP) ? KEYEVENTF_KEYUP : 0; ++ input.ki.time = GetTickCount(); ++ input.ki.dwExtraInfo = 0; ++ FromHaikuKeyCode(input.ki.wVk, input.ki.wScan, key); ++ ++ if (input.ki.wVk != 0) { ++ UnlockLooper(); ++ __wine_send_input(hwnd, &input, NULL); ++ LockLooper(); ++ } ++ return; ++ } ++ case B_MOUSE_DOWN: ++ case B_MOUSE_UP: ++ case B_MOUSE_MOVED: { ++ HWND hwnd = fHwnd; ++ //msg->FindPointer("hwnd", (void**)&hwnd); ++ BPoint where; ++ uint32 btns; ++ msg->FindPoint("screen_where", &where); ++ msg->FindInt32("buttons", (int32*)&btns); ++ //msg->FindInt32("old_buttons", (int32*)&oldBtns); ++ uint32 oldBtns = (msg->what == B_MOUSE_MOVED) ? btns : fOldMouseBtns; ++ fOldMouseBtns = btns; ++ uint32 btnsDown = btns & (~oldBtns); ++ uint32 btnsUp = oldBtns & (~btns); ++ ++ INPUT input; ++ input.type = INPUT_MOUSE; ++ input.mi.dx = (int)where.x; ++ input.mi.dy = (int)where.y; ++ input.mi.mouseData = 0; ++ input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; ++ input.mi.time = GetTickCount(); ++ input.mi.dwExtraInfo = 0; ++ ++ if ((1 << 0) & btnsDown) input.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN; ++ if ((1 << 1) & btnsDown) input.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN; ++ if ((1 << 2) & btnsDown) input.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN; ++ if ((1 << 0) & btnsUp) input.mi.dwFlags |= MOUSEEVENTF_LEFTUP; ++ if ((1 << 1) & btnsUp) input.mi.dwFlags |= MOUSEEVENTF_RIGHTUP; ++ if ((1 << 2) & btnsUp) input.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP; ++ ++ UnlockLooper(); ++ __wine_send_input(hwnd, &input, NULL); ++ LockLooper(); ++ return; ++ } ++ case B_MOUSE_WHEEL_CHANGED: { ++ HWND hwnd; ++ msg->FindPointer("hwnd", (void**)&hwnd); ++ float dx, dy; ++ if (msg->FindFloat("be:wheel_delta_x", &dx) < B_OK) dx = 0; ++ if (msg->FindFloat("be:wheel_delta_y", &dy) < B_OK) dy = 0; ++ int dxInt = int(-dx*WHEEL_DELTA); ++ int dyInt = int(-dy*WHEEL_DELTA); ++ DWORD time = GetTickCount(); ++ if (dxInt != 0) { ++ INPUT input; ++ input.type = INPUT_MOUSE; ++ input.mi.dx = 0; ++ input.mi.dy = 0; ++ input.mi.mouseData = dxInt; ++ input.mi.dwFlags = MOUSEEVENTF_HWHEEL; ++ input.mi.time = time; ++ input.mi.dwExtraInfo = 0; ++ UnlockLooper(); ++ __wine_send_input(hwnd, &input, NULL); ++ LockLooper(); ++ } ++ if (dyInt != 0) { ++ INPUT input; ++ input.type = INPUT_MOUSE; ++ input.mi.dx = 0; ++ input.mi.dy = 0; ++ input.mi.mouseData = dyInt; ++ input.mi.dwFlags = MOUSEEVENTF_WHEEL; ++ input.mi.time = time; ++ input.mi.dwExtraInfo = 0; ++ UnlockLooper(); ++ __wine_send_input(hwnd, &input, NULL); ++ LockLooper(); ++ } ++ return; ++ } ++ } ++/* ++ switch (msg->what) { ++ case B_KEY_DOWN: ++ case B_KEY_UP: ++ case B_UNMAPPED_KEY_DOWN: ++ case B_UNMAPPED_KEY_UP: { ++ msg->AddPointer("hwnd", fHwnd); ++ be_app_messenger.SendMessage(msg); ++ return; ++ } ++ case B_MOUSE_DOWN: ++ case B_MOUSE_UP: ++ case B_MOUSE_MOVED: { ++ msg->AddPointer("hwnd", fHwnd); ++ msg->AddInt32("old_buttons", (int32)fOldMouseBtns); ++ msg->FindInt32("buttons", (int32*)&fOldMouseBtns); ++ be_app_messenger.SendMessage(msg); ++ return; ++ } ++ case B_MOUSE_WHEEL_CHANGED: { ++ msg->AddPointer("hwnd", fHwnd); ++ be_app_messenger.SendMessage(msg); ++ return; ++ } ++ } ++*/ ++ BView::MessageReceived(msg); ++} ++ ++ ++WineWindow::WineWindow(HWND hwnd, struct haikudrv_thread_data *data, BRect frame): ++ BWindow(frame, "TestApp", B_NO_BORDER_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS), ++ fHwnd(hwnd), ++ fData(data), ++ fCreateMutex(MUTEX_INITIALIZER("create window")), ++ fSurface(NULL), ++ fSendResizeEvents(false), ++ fInDestroy(false), ++ fNonClient({0, 0, 0, 0}) ++{ ++ fView = new WineView(fHwnd, fData, Frame().OffsetToCopy(B_ORIGIN), "view"); ++ fView->SetResizingMode(B_FOLLOW_ALL); ++ AddChild(fView, NULL); ++ fView->MakeFocus(); ++} ++ ++WineWindow::~WineWindow() ++{} ++ ++bool WineWindow::QuitRequested() ++{ ++ if (fInDestroy) return true; ++ Unlock(); ++ HWND hwnd = fHwnd; ++ if (IsWindowEnabled(hwnd)) ++ { ++ HMENU hSysMenu; ++ ++ if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) { ++ Lock(); ++ return false; ++ } ++ hSysMenu = GetSystemMenu(hwnd, FALSE); ++ if (hSysMenu) ++ { ++ UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); ++ if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED))) { ++ Lock(); ++ return false; ++ } ++ } ++#if 0 ++ if (GetActiveWindow() != hwnd) ++ { ++ LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE, ++ (WPARAM)GetAncestor( hwnd, GA_ROOT ), ++ MAKELPARAM( HTCLOSE, WM_NCLBUTTONDOWN ) ); ++ switch(ma) ++ { ++ case MA_NOACTIVATEANDEAT: ++ case MA_ACTIVATEANDEAT: ++ Lock(); ++ return false; ++ case MA_NOACTIVATE: ++ break; ++ case MA_ACTIVATE: ++ case 0: ++ SetActiveWindow(hwnd); ++ break; ++ default: ++ WARN( "unknown WM_MOUSEACTIVATE code %d\n", (int) ma ); ++ break; ++ } ++ } ++#endif ++ PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 ); ++ } ++ Lock(); ++ return false; ++} ++ ++void WineWindow::FrameMoved(BPoint newPosition) ++{ ++ if (!fSendResizeEvents) return; ++ Unlock(); ++ SetWindowPos(fHwnd, 0, (int)newPosition.x - fNonClient.left, (int)newPosition.y - fNonClient.top, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); ++ Lock(); ++} ++ ++void WineWindow::FrameResized(float newWidth, float newHeight) ++{ ++ if (!fSendResizeEvents) return; ++ Unlock(); ++ SetWindowPos(fHwnd, 0, 0, 0, (int)newWidth + 1 + fNonClient.left + fNonClient.right, (int)newHeight + 1 + fNonClient.top + fNonClient.bottom, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); ++ Lock(); ++} ++ ++ ++WineApplication::WineApplication(): BApplication("application/x-vnd.Test-Wine") ++{ ++ InitKeymap(); ++} ++ ++//#pragma mark - ++ ++ ++DWORD sAppThread = 0; ++std::map *sWindows; ++ ++static UINT CALLBACK AppThread(void *arg) ++{ ++ rename_thread(find_thread(NULL), "application"); ++ be_app->Lock(); ++ be_app->Run(); ++ return 0; ++} ++ ++BOOL HaikuStartApplication() ++{ ++ if (be_app != NULL) { ++ ERR("be_app != NULL"); ++ _exit(1); ++ } ++ ++ sWindows = new std::map(); ++ ++ new WineApplication(); ++ be_app->Unlock(); ++ CloseHandle(CreateThread(NULL, 0, AppThread, NULL, 0, &sAppThread)); ++ return TRUE; ++} ++ ++static UINT CALLBACK WindowThread(void *arg) ++{ ++ rename_thread(find_thread(NULL), "window"); ++ auto wnd = (WineWindow*)arg; ++ wnd->Lock(); ++ mutex_unlock(&wnd->fCreateMutex); ++ wnd->Loop(); ++ return 0; ++} ++ ++static WineWindow* HaikuThisWindow(HWND hwnd, bool create = true) ++{ ++ BAutolock lock(be_app); ++ auto it = sWindows->find(hwnd); ++ if (it != sWindows->end()) ++ return it->second; ++ ++ if (!create) ++ return NULL; ++ ++ //struct haikudrv_thread_data *data = haikudrv_init_thread_data(); ++ WineWindow *window = new WineWindow(hwnd, NULL, BRect()); ++ (*sWindows)[hwnd] = window; ++ mutex_lock(&window->fCreateMutex); ++ window->Unlock(); ++ CloseHandle(CreateThread(NULL, 0, WindowThread, window, 0, &sAppThread)); ++ mutex_lock(&window->fCreateMutex); ++ return window; ++} ++ ++ ++//#pragma mark - window_surface ++ ++struct haikudrv_window_surface: public window_surface { ++ RECT bounds; ++ void *bits; ++ BBitmap *bitmap; ++ WineWindow *window; ++ CRITICAL_SECTION crit; ++ BITMAPINFO info; /* variable size, must be last */ ++}; ++ ++static struct haikudrv_window_surface *get_x11_surface(struct window_surface *surface) ++{ ++ return (struct haikudrv_window_surface *)surface; ++} ++ ++static inline int get_dib_info_size(const BITMAPINFO *info, UINT coloruse) ++{ ++ return FIELD_OFFSET( BITMAPINFO, bmiColors[0] ); ++/* ++ if (info->bmiHeader.biCompression == BI_BITFIELDS) ++ return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD); ++ if (coloruse == DIB_PAL_COLORS) ++ return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD); ++ if (!info->bmiHeader.biClrUsed && info->bmiHeader.biBitCount <= 8) ++ return FIELD_OFFSET( BITMAPINFO, bmiColors[1 << info->bmiHeader.biBitCount] ); ++ return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] ); ++*/ ++} ++ ++ ++static void CDECL haikudrv_surface_lock(struct window_surface *window_surface) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface(window_surface); ++ EnterCriticalSection(&surface->crit); ++} ++ ++static void CDECL haikudrv_surface_unlock(struct window_surface *window_surface) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface(window_surface); ++ LeaveCriticalSection(&surface->crit); ++} ++ ++static void *CDECL haikudrv_surface_get_bitmap_info(struct window_surface *window_surface, BITMAPINFO *info) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface( window_surface ); ++ ++ memcpy( info, &surface->info, get_dib_info_size(&surface->info, DIB_RGB_COLORS)); ++ return surface->bits; ++} ++ ++static RECT *CDECL haikudrv_surface_get_bounds(struct window_surface *window_surface) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface(window_surface); ++ return &surface->bounds; ++} ++ ++static void CDECL haikudrv_surface_set_region(struct window_surface *window_surface, HRGN region) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface(window_surface); ++ ++ window_surface->funcs->lock(window_surface); ++ // ... ++ window_surface->funcs->unlock(window_surface); ++} ++ ++static void CDECL haikudrv_surface_flush(struct window_surface *window_surface) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface(window_surface); ++ ++ window_surface->funcs->lock(window_surface); ++ //FIXME("(): stub\n"); ++ RECT dirty; ++ SetRect(&dirty, 0, 0, surface->rect.right - surface->rect.left, surface->rect.bottom - surface->rect.top); ++ if (IntersectRect( &dirty, &dirty, &surface->bounds )) { ++ surface->window->Lock(); ++ BRect dirtyRect(dirty.left, dirty.top, dirty.right - 1, dirty.bottom - 1); ++ surface->window->View()->UpdateBitmap(surface->bitmap, dirtyRect); ++ surface->window->Unlock(); ++ } ++ reset_bounds(&surface->bounds); ++ window_surface->funcs->unlock(window_surface); ++} ++ ++static void CDECL haikudrv_surface_destroy(struct window_surface *window_surface) ++{ ++ struct haikudrv_window_surface *surface = get_x11_surface( window_surface ); ++ ++ delete surface->bitmap; surface->bitmap = NULL; ++ surface->crit.DebugInfo->Spare[0] = 0; ++ DeleteCriticalSection(&surface->crit); ++ HeapFree(GetProcessHeap(), 0, surface); ++} ++ ++static const struct window_surface_funcs haikudrv_surface_funcs = { ++ haikudrv_surface_lock, ++ haikudrv_surface_unlock, ++ haikudrv_surface_get_bitmap_info, ++ haikudrv_surface_get_bounds, ++ haikudrv_surface_set_region, ++ haikudrv_surface_flush, ++ haikudrv_surface_destroy ++}; ++ ++struct window_surface *create_surface(WineWindow *window, const RECT *rect, COLORREF color_key, BOOL use_alpha) ++{ ++ struct haikudrv_window_surface *surface; ++ int width = rect->right - rect->left, height = rect->bottom - rect->top; ++ ++ surface = (haikudrv_window_surface*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(struct haikudrv_window_surface, info.bmiColors[0])); ++ if (!surface) return NULL; ++ ++ surface->window = window; ++ ++ surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); ++ surface->info.bmiHeader.biWidth = width; ++ surface->info.bmiHeader.biHeight = -height; /* top-down */ ++ surface->info.bmiHeader.biPlanes = 1; ++ surface->info.bmiHeader.biBitCount = 32; ++ surface->info.bmiHeader.biSizeImage = 4*width*height; ++ surface->info.bmiHeader.biCompression = BI_RGB; ++ surface->info.bmiHeader.biClrUsed = 0; ++ ++ InitializeCriticalSection( &surface->crit ); ++ surface->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface"); ++ ++ surface->funcs = &haikudrv_surface_funcs; ++ surface->rect = *rect; ++ surface->ref = 1; ++ reset_bounds(&surface->bounds); ++ ++ surface->bitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), B_RGBA32); ++ if (!surface->bitmap) { ++ goto failed; ++ } ++ surface->bits = surface->bitmap->Bits(); ++ ++ return surface; ++ ++failed: ++ haikudrv_surface_destroy(surface); ++ return NULL; ++} ++ ++ ++//#pragma mark - ++ ++/*********************************************************************** ++ * ThreadDetach (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_ThreadDetach(void) ++{ ++#if 0 ++ struct haikudrv_thread_data *data = (struct haikudrv_thread_data*)TlsGetValue( thread_data_tls_index ); ++ ++ if (data) ++ { ++ delete data; ++ /* clear data in case we get re-entered from user32 before the thread is truly dead */ ++ TlsSetValue( thread_data_tls_index, NULL ); ++ } ++#endif ++} ++ ++ ++/*********************************************************************** ++ * HAIKUDRV thread initialisation routine ++ */ ++struct haikudrv_thread_data *haikudrv_init_thread_data(void) ++{ ++ struct haikudrv_thread_data *data = haikudrv_thread_data(); ++ ++ if (data) return data; ++ ++ if (!(data = new(std::nothrow) struct haikudrv_thread_data())) ++ { ++ ERR( "could not create data\n" ); ++ ExitProcess(1); ++ } ++ ++ TlsSetValue( thread_data_tls_index, data ); ++ ++ return data; ++} ++ ++//#pragma mark - ++ ++struct has_popup_result ++{ ++ HWND hwnd; ++ BOOL found; ++}; ++ ++static BOOL is_managed( HWND hwnd ) ++{ ++ WineWindow *wnd = HaikuThisWindow(hwnd, false); ++ return wnd != NULL; ++} ++ ++static BOOL CALLBACK has_managed_popup( HWND hwnd, LPARAM lparam ) ++{ ++ struct has_popup_result *result = (struct has_popup_result *)lparam; ++ ++ if (hwnd == result->hwnd) return FALSE; /* popups are always above owner */ ++ if (GetWindow( hwnd, GW_OWNER ) != result->hwnd) return TRUE; ++ result->found = is_managed( hwnd ); ++ return !result->found; ++} ++ ++static BOOL has_owned_popups( HWND hwnd ) ++{ ++ struct has_popup_result result; ++ ++ result.hwnd = hwnd; ++ result.found = FALSE; ++ EnumWindows( has_managed_popup, (LPARAM)&result ); ++ return result.found; ++} ++ ++static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ) ++{ ++ DWORD style, ex_style; ++ ++ /* child windows are not managed */ ++ style = GetWindowLongW( hwnd, GWL_STYLE ); ++ if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) return FALSE; ++ return TRUE; ++ ++ /* activated windows are managed */ ++ if (!(swp_flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) return TRUE; ++ if (hwnd == GetActiveWindow()) return TRUE; ++ /* windows with caption are managed */ ++ if ((style & WS_CAPTION) == WS_CAPTION) return TRUE; ++ /* windows with thick frame are managed */ ++ if (style & WS_THICKFRAME) return TRUE; ++ if (style & WS_POPUP) { ++ HMONITOR hmon; ++ MONITORINFO mi; ++ ++ /* popup with sysmenu == caption are managed */ ++ if (style & WS_SYSMENU) return TRUE; ++ /* full-screen popup windows are managed */ ++ hmon = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY ); ++ mi.cbSize = sizeof( mi ); ++ GetMonitorInfoW( hmon, &mi ); ++ if (window_rect->left <= mi.rcWork.left && window_rect->right >= mi.rcWork.right && ++ window_rect->top <= mi.rcWork.top && window_rect->bottom >= mi.rcWork.bottom) ++ return TRUE; ++ } ++ /* application windows are managed */ ++ ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); ++ if (ex_style & WS_EX_APPWINDOW) return TRUE; ++ /* windows that own popups are managed */ ++ if (has_owned_popups( hwnd )) return TRUE; ++ /* default: not managed */ ++ return FALSE; ++} ++ ++ ++ ++/********************************************************************** ++ * is_owned_by ++ */ ++static BOOL is_owned_by(HWND hwnd, HWND maybe_owner) ++{ ++ while (1) ++ { ++ HWND hwnd2 = GetWindow(hwnd, GW_OWNER); ++ if (!hwnd2) ++ hwnd2 = GetAncestor(hwnd, GA_ROOT); ++ if (!hwnd2 || hwnd2 == hwnd) ++ break; ++ if (hwnd2 == maybe_owner) ++ return TRUE; ++ hwnd = hwnd2; ++ } ++ ++ return FALSE; ++} ++ ++ ++/********************************************************************** ++ * is_all_the_way_front ++ */ ++static BOOL is_all_the_way_front(HWND hwnd) ++{ ++ BOOL topmost = (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; ++ HWND prev = hwnd; ++ ++ while ((prev = GetWindow(prev, GW_HWNDPREV))) ++ { ++ if (!topmost && (GetWindowLongW(prev, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0) ++ return TRUE; ++ if (!is_owned_by(prev, hwnd)) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect ) ++{ ++ *surface_rect = (RECT){0, 0, 4096, 4096}; ++ ++ if (!IntersectRect( surface_rect, surface_rect, visible_rect )) return FALSE; ++ OffsetRect( surface_rect, -visible_rect->left, -visible_rect->top ); ++ surface_rect->left &= ~31; ++ surface_rect->top &= ~31; ++ surface_rect->right = max( surface_rect->left + 32, (surface_rect->right + 31) & ~31 ); ++ surface_rect->bottom = max( surface_rect->top + 32, (surface_rect->bottom + 31) & ~31 ); ++ return TRUE; ++} ++ ++static RECT get_virtual_screen_rect() ++{ ++ BRect frame = BScreen().Frame(); ++ return RECT{ ++ .left = (int)frame.left, ++ .top = (int)frame.top, ++ .right = (int)frame.right + 1, ++ .bottom = (int)frame.bottom + 1, ++ }; ++} ++ ++static void GetHaikuWindowFlags( ++ uint32 &flags, ++ window_look &look, ++ window_feel &feel, ++ WineWindow *wnd, ++ DWORD style, DWORD ex_style, ++ const RECT *window_rect, ++ const RECT *client_rect ++) ++{ ++ flags = B_NOT_CLOSABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_NOT_RESIZABLE | ++ B_ASYNCHRONOUS_CONTROLS | B_WILL_ACCEPT_FIRST_CLICK; ++ look = B_NO_BORDER_WINDOW_LOOK; ++ feel = B_NORMAL_WINDOW_FEEL; ++ ++ //if (disable_window_decorations) return; ++ if (IsRectEmpty(window_rect)) return; ++ if (EqualRect(window_rect, client_rect)) return; ++ ++ if ((style & WS_CAPTION) == WS_CAPTION && !(ex_style & WS_EX_LAYERED)) ++ { ++ look = B_MODAL_WINDOW_LOOK; ++ if (true/*!data->shaped*/) ++ { ++ look = B_TITLED_WINDOW_LOOK; ++ if (style & WS_SYSMENU) flags &= ~B_NOT_CLOSABLE; ++ if (style & WS_MINIMIZEBOX) flags &= ~B_NOT_MINIMIZABLE; ++ if (style & WS_MAXIMIZEBOX) flags &= ~B_NOT_ZOOMABLE; ++ if (ex_style & WS_EX_TOOLWINDOW) look = B_FLOATING_WINDOW_LOOK; ++ } ++ } ++ if (style & WS_THICKFRAME) ++ { ++ if (look == B_NO_BORDER_WINDOW_LOOK) look = B_MODAL_WINDOW_LOOK; ++ if (true/*!data->shaped*/) flags &= ~B_NOT_RESIZABLE; ++ } ++ else if (ex_style & WS_EX_DLGMODALFRAME) {if (look == B_NO_BORDER_WINDOW_LOOK) look = B_MODAL_WINDOW_LOOK;} ++ else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) {if (look == B_NO_BORDER_WINDOW_LOOK) look = B_MODAL_WINDOW_LOOK;} ++} ++ ++ ++/***************************************************************** ++ * SetWindowText (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_SetWindowText( HWND hwnd, LPCWSTR text ) ++{ ++ UINT count; ++ char *utf8_buffer; ++ count = WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), NULL, 0, NULL, NULL); ++ if (!(utf8_buffer = (char*)HeapAlloc( GetProcessHeap(), 0, count + 1 ))) { ++ return; ++ } ++ WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), utf8_buffer, count, NULL, NULL); ++ utf8_buffer[count] = 0; ++ ++ //FIXME("(%ld, \"%s\"): stub\n", (long)hwnd, utf8_buffer); ++ ++ WineWindow *wnd = HaikuThisWindow(hwnd, false); ++ if (wnd == NULL) return; ++ wnd->Lock(); ++ wnd->SetTitle(utf8_buffer); ++ wnd->Unlock(); ++ ++ HeapFree( GetProcessHeap(), 0, utf8_buffer ); ++} ++ ++ ++/*********************************************************************** ++ * SetWindowStyle (HAIKUDRV.@) ++ * ++ * Update the X state of a window to reflect a style change ++ */ ++void CDECL HAIKUDRV_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/*********************************************************************** ++ * DestroyWindow (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_DestroyWindow( HWND hwnd ) ++{ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++ WineWindow *wnd = HaikuThisWindow(hwnd, false); ++ if (wnd == NULL) return; ++ wnd->Lock(); ++ wnd->fInDestroy = true; ++ BMessenger(wnd).SendMessage(B_QUIT_REQUESTED); ++ wnd->Unlock(); ++} ++ ++ ++/********************************************************************** ++ * CreateDesktopWindow (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_CreateDesktopWindow( HWND hwnd ) ++{ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++ RECT oldRect; ++ ++ /* retrieve the real size of the desktop */ ++ SERVER_START_REQ( get_window_rectangles ) ++ { ++ req->handle = wine_server_user_handle( hwnd ); ++ req->relative = COORDS_CLIENT; ++ wine_server_call( req ); ++ oldRect.left = reply->window.left; ++ oldRect.top = reply->window.top; ++ oldRect.right = reply->window.right; ++ oldRect.bottom = reply->window.bottom; ++ } ++ SERVER_END_REQ; ++ ++ RECT rect = get_virtual_screen_rect(); ++ ERR("desktop rect: (%d, %d, %d, %d)\n", rect.left, rect.top, rect.right, rect.bottom); ++ if (!EqualRect(&oldRect, &rect)) ++ { ++ ++ SERVER_START_REQ( set_window_pos ) ++ { ++ req->handle = wine_server_user_handle( hwnd ); ++ req->previous = 0; ++ req->swp_flags = SWP_NOZORDER; ++ req->window.left = rect.left; ++ req->window.top = rect.top; ++ req->window.right = rect.right; ++ req->window.bottom = rect.bottom; ++ req->client = req->window; ++ wine_server_call( req ); ++ } ++ SERVER_END_REQ; ++ } ++ return TRUE; ++} ++ ++ ++/********************************************************************** ++ * CreateWindow (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_CreateWindow( HWND hwnd ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++ return TRUE; ++} ++ ++ ++/*********************************************************************** ++ * HAIKUDRV_GetDC (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_GetDC( HDC hdc, HWND hwnd, HWND top, const RECT *win_rect, ++ const RECT *top_rect, DWORD flags ) ++{ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/*********************************************************************** ++ * HAIKUDRV_ReleaseDC (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_ReleaseDC( HWND hwnd, HDC hdc ) ++{ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/************************************************************************* ++ * ScrollDC (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ) ++{ ++ FIXME("(%ld): stub\n", (long)hdc); ++ return FALSE; ++} ++ ++ ++/*********************************************************************** ++ * SetCapture (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_SetCapture( HWND hwnd, UINT flags ) ++{ ++ FIXME("(%ld, %x): stub\n", (long)hwnd, flags); ++ return; ++ if (hwnd == sCaptureWnd) return; ++ WineWindow* prevWnd = HaikuThisWindow(sCaptureWnd, false); ++ if (prevWnd != NULL) { ++ prevWnd->Lock(); ++ prevWnd->View()->SetEventMask(0); ++ prevWnd->Unlock(); ++ } ++ WineWindow* nextWnd = HaikuThisWindow(hwnd, false); ++ if (nextWnd != NULL) { ++ nextWnd->Lock(); ++ nextWnd->View()->SetEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS); ++ nextWnd->Unlock(); ++ } ++} ++ ++ ++/***************************************************************** ++ * SetParent (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/*********************************************************************** ++ * WindowPosChanging (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, ++ const RECT *window_rect, const RECT *client_rect, RECT *visible_rect, ++ struct window_surface **surface ) ++{ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++ ERR("(%ld)\n", (long)hwnd); ++ ++ if (hwnd == GetDesktopWindow()) return TRUE; ++ if (!is_window_managed( hwnd, swp_flags, window_rect )) return TRUE; ++ ++ ERR("window_rect: (%d, %d, %d, %d)\n", window_rect->left, window_rect->top, window_rect->right, window_rect->bottom); ++ ERR("client_rect: (%d, %d, %d, %d)\n", client_rect->left, client_rect->top, client_rect->right, client_rect->bottom); ++ ++ DWORD style = GetWindowLongW(hwnd, GWL_STYLE); ++ DWORD exStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); ++ RECT adjRect = *client_rect; ++ AdjustWindowRectEx(&adjRect, style, FALSE, exStyle); ++ adjRect = { ++ client_rect->left - adjRect.left, ++ client_rect->top - adjRect.top, ++ adjRect.right - client_rect->right, ++ adjRect.bottom - client_rect->bottom ++ }; ++ *visible_rect = { ++ window_rect->left + adjRect.left, ++ window_rect->top + adjRect.top, ++ window_rect->right - adjRect.right, ++ window_rect->bottom - adjRect.bottom, ++ }; ++ ++ RECT surface_rect = { ++ 0, 0, ++ visible_rect->right - visible_rect->left, ++ visible_rect->bottom - visible_rect->top, ++ }; ++ //if (!get_surface_rect( visible_rect, &surface_rect )) return FALSE; ++ ++ WineWindow *window = HaikuThisWindow(hwnd); ++ ++ if (window->fSurface) { ++ if (EqualRect( &window->fSurface->rect, &surface_rect )) { ++ /* existing surface is good enough */ ++ window_surface_add_ref( window->fSurface ); ++ *surface = window->fSurface; ++ return TRUE; ++ } ++ } ++ ++ *surface = create_surface(window, &surface_rect, 0, FALSE); ++ return TRUE; ++} ++ ++ ++/*********************************************************************** ++ * WindowPosChanged (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, ++ const RECT *rectWindow, const RECT *rectClient, ++ const RECT *visible_rect, const RECT *valid_rects, ++ struct window_surface *surface ) ++{ ++ ERR("(%ld)\n", (long)hwnd); ++ WineWindow *window = HaikuThisWindow(hwnd, false); ++ if (window == NULL) return; ++ ++ ERR("(%p, swp_flags: %x)\n", hwnd, swp_flags); ++ ++ DWORD style = GetWindowLongW(hwnd, GWL_STYLE); ++ DWORD exStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); ++ ++ window->Lock(); ++ window->fNonClient = { ++ visible_rect->left - rectWindow->left, ++ visible_rect->top - rectWindow->top, ++ rectWindow->right - visible_rect->right, ++ rectWindow->bottom - visible_rect->bottom ++ }; ++ window->MoveTo(visible_rect->left, visible_rect->top); ++ window->ResizeTo(visible_rect->right - visible_rect->left - 1, visible_rect->bottom - visible_rect->top - 1); ++ ++ uint32 newFlags; ++ window_look newLook; ++ window_feel newFeel; ++ GetHaikuWindowFlags(newFlags, newLook, newFeel, window, style, exStyle, rectWindow, rectClient); ++ if (window->Flags() != newFlags) window->SetFlags(newFlags); ++ if (window->Look() != newLook) window->SetLook(newLook); ++ if (window->Feel() != newFeel) window->SetFeel(newFeel); ++ ++ bool newVisible = (style & WS_VISIBLE) != 0; ++ if (newVisible != !window->IsHidden()) { ++ if (newVisible) { ++ if (SWP_NOACTIVATE & swp_flags) window->SetFlags(window->Flags() | B_AVOID_FOCUS); ++ window->Show(); ++ if (SWP_NOACTIVATE & swp_flags) window->SetFlags(window->Flags() & ~B_AVOID_FOCUS); ++ window->fSendResizeEvents = true; ++ } else { ++ window->Hide(); ++ window->fSendResizeEvents = false; ++ } ++ } else { ++ if (!window->IsHidden() && !(SWP_NOACTIVATE & swp_flags)) { ++ ERR("(%p): Activate\n", hwnd); ++ window->Activate(); ++ } ++ } ++ window->Unlock(); ++ ++ //FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++/*********************************************************************** ++ * ShowWindow (HAIKUDRV.@) ++ */ ++UINT CDECL HAIKUDRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++ return swp; ++} ++ ++ ++/********************************************************************** ++ * SetWindowIcon (HAIKUDRV.@) ++ * ++ * hIcon or hIconSm has changed (or is being initialised for the ++ * first time). Complete the X11 driver-specific initialisation ++ * and set the window hints. ++ */ ++void CDECL HAIKUDRV_SetWindowIcon( HWND hwnd, UINT type, HICON icon ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/*********************************************************************** ++ * SetWindowRgn (HAIKUDRV.@) ++ * ++ * Assign specified region to window (for non-rectangular windows) ++ */ ++void CDECL HAIKUDRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/*********************************************************************** ++ * SetLayeredWindowAttributes (HAIKUDRV.@) ++ * ++ * Set transparency attributes for a layered window. ++ */ ++void CDECL HAIKUDRV_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++} ++ ++ ++/***************************************************************************** ++ * UpdateLayeredWindow (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, ++ const RECT *window_rect ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++ return TRUE; ++} ++ ++/********************************************************************** ++ * HAIKUDRV_WindowMessage (HAIKUDRV.@) ++ */ ++LRESULT CDECL HAIKUDRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++ return 0; ++} ++ ++/*********************************************************************** ++ * HAIKUDRV_SysCommand (HAIKUDRV.@) ++ * ++ * Perform WM_SYSCOMMAND handling. ++ */ ++LRESULT CDECL HAIKUDRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) ++{ ++ FIXME("(%ld): stub\n", (long)hwnd); ++ return -1; ++} ++ ++/*********************************************************************** ++ * HAIKUDRV_FlashWindowEx (HAIKUDRV.@) ++ */ ++void CDECL HAIKUDRV_FlashWindowEx( PFLASHWINFO pfinfo ) ++{ ++} ++ ++/*********************************************************************** ++ * MsgWaitForMultipleObjectsEx (HAIKUDRV.@) ++ */ ++DWORD CDECL HAIKUDRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, ++ DWORD timeout, DWORD mask, DWORD flags ) ++{ ++ timeout = timeout < 1000 ? timeout : 1000; ++ //struct haikudrv_thread_data *data = haikudrv_init_thread_data(); ++ //if (data == NULL) { ++ if (!count && !timeout) return WAIT_TIMEOUT; ++ return WaitForMultipleObjectsEx(count, handles, flags & MWMO_WAITALL, timeout, flags & MWMO_ALERTABLE); ++ //} ++/* ++ data->ProcessMessages(); ++ ++ if (!count && !timeout) return WAIT_TIMEOUT; ++ return WaitForMultipleObjectsEx(count, handles, flags & MWMO_WAITALL, timeout, flags & MWMO_ALERTABLE); ++*/ ++} ++ ++/***************************************************************** ++ * SetFocus (HAIKUDRV.@) ++ * ++ * Set the X focus. ++ */ ++void CDECL HAIKUDRV_SetFocus( HWND hwnd ) ++{ ++ FIXME("(%ld)\n", (long)hwnd); ++ if (!(hwnd = GetAncestor(hwnd, GA_ROOT))) return; ++ ++ if (hwnd == GetForegroundWindow() && hwnd != GetDesktopWindow() && !is_all_the_way_front(hwnd)) ++ SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); ++ ++ WineWindow *window = HaikuThisWindow(hwnd, false); ++ if (window == NULL) return; ++ window->Activate(); ++} ++ ++ ++/*********************************************************************** ++ * ToUnicodeEx (HAIKUDRV.@) ++ * ++ * The ToUnicode function translates the specified virtual-key code and keyboard ++ * state to the corresponding Windows character or characters. ++ * ++ * If the specified key is a dead key, the return value is negative. Otherwise, ++ * it is one of the following values: ++ * Value Meaning ++ * 0 The specified virtual key has no translation for the current state of the keyboard. ++ * 1 One Windows character was copied to the buffer. ++ * 2 Two characters were copied to the buffer. This usually happens when a ++ * dead-key character (accent or diacritic) stored in the keyboard layout cannot ++ * be composed with the specified virtual key to form a single character. ++ * ++ * FIXME : should do the above (return 2 for non matching deadchar+char combinations) ++ * ++ */ ++INT CDECL HAIKUDRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState, ++ LPWSTR bufW, int bufW_size, UINT flags, HKL hkl) ++{ ++ //FIXME("(%u): stub\n", virtKey); ++ if (virtKey >= 256) return -2; ++ uint32 key = sHaikuFromVkKeycodes[virtKey]; ++ uint32 modifiers = HaikuModifiersFromKeyState(lpKeyState); ++ ++ char *srcChars; ++ size_t srcLen; ++ MapKey(srcChars, srcLen, key, modifiers); ++ ++ INT dstLen = MultiByteToWideChar(CP_UTF8, 0, srcChars, srcLen, NULL, 0); ++ MultiByteToWideChar(CP_UTF8, 0, srcChars, srcLen, bufW, bufW_size); ++ return dstLen; ++} +diff --git a/dlls/winehaiku.drv/winehaiku.drv.spec b/dlls/winehaiku.drv/winehaiku.drv.spec +new file mode 100644 +index 00000000000..9be88c47358 +--- /dev/null ++++ b/dlls/winehaiku.drv/winehaiku.drv.spec +@@ -0,0 +1,29 @@ ++# WinTab32 ++@ cdecl AttachEventQueueToTablet(long) HAIKUDRV_AttachEventQueueToTablet ++@ cdecl GetCurrentPacket(ptr) HAIKUDRV_GetCurrentPacket ++@ cdecl LoadTabletInfo(long) HAIKUDRV_LoadTabletInfo ++@ cdecl WTInfoW(long long ptr) HAIKUDRV_WTInfoW ++ ++# Desktop ++@ cdecl wine_create_desktop(long long) HAIKUDRV_create_desktop ++ ++# System tray ++@ cdecl wine_notify_icon(long ptr) ++ ++#IME Interface ++@ stdcall ImeInquire(ptr ptr wstr) ++@ stdcall ImeConfigure(long long long ptr) ++@ stdcall ImeDestroy(long) ++@ stdcall ImeEscape(long long ptr) ++@ stdcall ImeSelect(long long) ++@ stdcall ImeSetActiveContext(long long) ++@ stdcall ImeToAsciiEx(long long ptr ptr long long) ++@ stdcall NotifyIME(long long long long) ++@ stdcall ImeRegisterWord(wstr long wstr) ++@ stdcall ImeUnregisterWord(wstr long wstr) ++@ stdcall ImeEnumRegisterWord(ptr wstr long wstr ptr) ++@ stdcall ImeSetCompositionString(long long ptr long ptr long) ++@ stdcall ImeConversionList(long wstr ptr long long) ++@ stdcall ImeProcessKey(long long long ptr) ++@ stdcall ImeGetRegisterWordStyle(long ptr) ++@ stdcall ImeGetImeMenuItems(long long long ptr ptr long) +diff --git a/dlls/winehaiku.drv/wintab.c b/dlls/winehaiku.drv/wintab.c +new file mode 100644 +index 00000000000..47e0e9a4681 +--- /dev/null ++++ b/dlls/winehaiku.drv/wintab.c +@@ -0,0 +1,69 @@ ++/* ++ * X11 tablet driver ++ * ++ * Copyright 2003 CodeWeavers (Aric Stewart) ++ * ++ * 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 ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++#include "winnls.h" ++#include "haikudrv.h" ++#include "wine/unicode.h" ++#include "wine/debug.h" ++#include "wintab.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(wintab32); ++ ++ ++/*********************************************************************** ++ * HAIKUDRV_LoadTabletInfo (HAIKUDRV.@) ++ */ ++BOOL CDECL HAIKUDRV_LoadTabletInfo(HWND hwnddefault) ++{ ++ return FALSE; ++} ++ ++/*********************************************************************** ++ * HAIKUDRV_AttachEventQueueToTablet (HAIKUDRV.@) ++ */ ++int CDECL HAIKUDRV_AttachEventQueueToTablet(HWND hOwner) ++{ ++ return 0; ++} ++ ++/*********************************************************************** ++ * HAIKUDRV_GetCurrentPacket (HAIKUDRV.@) ++ */ ++int CDECL HAIKUDRV_GetCurrentPacket(/*LPWTPACKET*/void* packet) ++{ ++ return 0; ++} ++ ++/*********************************************************************** ++ * HAIKUDRV_WTInfoW (HAIKUDRV.@) ++ */ ++UINT CDECL HAIKUDRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput) ++{ ++ return 0; ++} +diff --git a/include/wine/server.h b/include/wine/server.h +index 57bcdbbb00d..5f3327b20a8 100644 +--- a/include/wine/server.h ++++ b/include/wine/server.h +@@ -70,7 +70,7 @@ static inline data_size_t wine_server_reply_size( const void *reply ) + /* add some data to be sent along with the request */ + static inline void wine_server_add_data( void *req_ptr, const void *ptr, data_size_t size ) + { +- struct __server_request_info * const req = req_ptr; ++ struct __server_request_info * const req = (struct __server_request_info * const)req_ptr; + if (size) + { + req->data[req->data_count].ptr = ptr; +@@ -82,7 +82,7 @@ static inline void wine_server_add_data( void *req_ptr, const void *ptr, data_si + /* set the pointer and max size for the reply var data */ + static inline void wine_server_set_reply( void *req_ptr, void *ptr, data_size_t max_size ) + { +- struct __server_request_info * const req = req_ptr; ++ struct __server_request_info * const req = (struct __server_request_info * const)req_ptr; + req->reply_data = ptr; + req->u.req.request_header.reply_size = max_size; + } +diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h +index c2a2acfc282..853244058d9 100644 +--- a/include/wine/vulkan_driver.h ++++ b/include/wine/vulkan_driver.h +@@ -56,17 +56,17 @@ static inline void *get_vulkan_driver_device_proc_addr( + name += 2; + + if (!strcmp(name, "CreateSwapchainKHR")) +- return vulkan_funcs->p_vkCreateSwapchainKHR; ++ return (void*)vulkan_funcs->p_vkCreateSwapchainKHR; + if (!strcmp(name, "DestroySwapchainKHR")) +- return vulkan_funcs->p_vkDestroySwapchainKHR; ++ return (void*)vulkan_funcs->p_vkDestroySwapchainKHR; + if (!strcmp(name, "GetDeviceGroupSurfacePresentModesKHR")) +- return vulkan_funcs->p_vkGetDeviceGroupSurfacePresentModesKHR; ++ return (void*)vulkan_funcs->p_vkGetDeviceGroupSurfacePresentModesKHR; + if (!strcmp(name, "GetDeviceProcAddr")) +- return vulkan_funcs->p_vkGetDeviceProcAddr; ++ return (void*)vulkan_funcs->p_vkGetDeviceProcAddr; + if (!strcmp(name, "GetSwapchainImagesKHR")) +- return vulkan_funcs->p_vkGetSwapchainImagesKHR; ++ return (void*)vulkan_funcs->p_vkGetSwapchainImagesKHR; + if (!strcmp(name, "QueuePresentKHR")) +- return vulkan_funcs->p_vkQueuePresentKHR; ++ return (void*)vulkan_funcs->p_vkQueuePresentKHR; + + return NULL; + } +@@ -79,36 +79,36 @@ static inline void *get_vulkan_driver_instance_proc_addr( + name += 2; + + if (!strcmp(name, "CreateInstance")) +- return vulkan_funcs->p_vkCreateInstance; ++ return (void*)vulkan_funcs->p_vkCreateInstance; + if (!strcmp(name, "EnumerateInstanceExtensionProperties")) +- return vulkan_funcs->p_vkEnumerateInstanceExtensionProperties; ++ return (void*)vulkan_funcs->p_vkEnumerateInstanceExtensionProperties; + + if (!instance) return NULL; + + if (!strcmp(name, "CreateWin32SurfaceKHR")) +- return vulkan_funcs->p_vkCreateWin32SurfaceKHR; ++ return (void*)vulkan_funcs->p_vkCreateWin32SurfaceKHR; + if (!strcmp(name, "DestroyInstance")) +- return vulkan_funcs->p_vkDestroyInstance; ++ return (void*)vulkan_funcs->p_vkDestroyInstance; + if (!strcmp(name, "DestroySurfaceKHR")) +- return vulkan_funcs->p_vkDestroySurfaceKHR; ++ return (void*)vulkan_funcs->p_vkDestroySurfaceKHR; + if (!strcmp(name, "GetInstanceProcAddr")) +- return vulkan_funcs->p_vkGetInstanceProcAddr; ++ return (void*)vulkan_funcs->p_vkGetInstanceProcAddr; + if (!strcmp(name, "GetPhysicalDevicePresentRectanglesKHR")) +- return vulkan_funcs->p_vkGetPhysicalDevicePresentRectanglesKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDevicePresentRectanglesKHR; + if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2KHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilities2KHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilities2KHR; + if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilitiesKHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; + if (!strcmp(name, "GetPhysicalDeviceSurfaceFormats2KHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormats2KHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormats2KHR; + if (!strcmp(name, "GetPhysicalDeviceSurfaceFormatsKHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR; + if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModesKHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfacePresentModesKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfacePresentModesKHR; + if (!strcmp(name, "GetPhysicalDeviceSurfaceSupportKHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceSurfaceSupportKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceSurfaceSupportKHR; + if (!strcmp(name, "GetPhysicalDeviceWin32PresentationSupportKHR")) +- return vulkan_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR; ++ return (void*)vulkan_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR; + + name -= 2; + +diff --git a/include/winuser.h b/include/winuser.h +index 898c9034e33..048f86e9956 100644 +--- a/include/winuser.h ++++ b/include/winuser.h +@@ -4442,7 +4442,7 @@ struct user_api_hook + LRESULT (WINAPI *pScrollBarWndProc)(HWND, UINT, WPARAM, LPARAM, BOOL); + }; + +-WINUSERAPI BOOL WINAPI RegisterUserApiHook(const struct user_api_hook *new, struct user_api_hook *old); ++WINUSERAPI BOOL WINAPI RegisterUserApiHook(const struct user_api_hook *newHook, struct user_api_hook *oldHook); + WINUSERAPI void WINAPI UnregisterUserApiHook(void); + #endif + +diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c +index 6d577dd0fd1..c96a85f2d60 100644 +--- a/programs/explorer/desktop.c ++++ b/programs/explorer/desktop.c +@@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(explorer); + #define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769)) + #define DESKTOP_ALL_ACCESS 0x01ff + +-static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0}; ++static const WCHAR default_driver[] = L"haiku,mac,x11"; + + static BOOL using_root; + +-- +2.30.2 + + +From 1e8491ce2859de2d937b78bbeca413bd7f4efb30 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Thu, 20 Jan 2022 22:28:08 +0900 +Subject: winehaiku.drv: stand alone Vulkan WSI implementation + +--- + dlls/winehaiku.drv/Makefile.in | 2 +- + dlls/winehaiku.drv/vulkan.cpp | 849 ++++++++++++++++++++++++++++++--- + 2 files changed, 787 insertions(+), 64 deletions(-) + +diff --git a/dlls/winehaiku.drv/Makefile.in b/dlls/winehaiku.drv/Makefile.in +index 0db76dd3a93..6a8d910ed66 100644 +--- a/dlls/winehaiku.drv/Makefile.in ++++ b/dlls/winehaiku.drv/Makefile.in +@@ -2,7 +2,7 @@ MODULE = winehaiku.drv + IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32 win32u + DELAYIMPORTS = comctl32 ole32 shell32 imm32 + EXTRAINCL = -I/boot/system/develop/headers/private/shared +-EXTRALIBS = -lbe -lstdc++ -lvulkan ++EXTRALIBS = -lbe -lgame -lstdc++ -lvulkan + + EXTRADLLFLAGS = -mcygwin + +diff --git a/dlls/winehaiku.drv/vulkan.cpp b/dlls/winehaiku.drv/vulkan.cpp +index 32929122ff7..59bf952ebb7 100644 +--- a/dlls/winehaiku.drv/vulkan.cpp ++++ b/dlls/winehaiku.drv/vulkan.cpp +@@ -1,3 +1,5 @@ ++#include ++ + extern "C" { + #include "config.h" + #include "haikudrv.h" +@@ -9,9 +11,14 @@ extern "C" { + #include "wine/vulkan.h" + #include "wine/vulkan_driver.h" + } ++#include ++#include ++#include ++#include ++#include + #include + +-WINE_DEFAULT_DEBUG_CHANNEL(vulkan); ++WINE_DEFAULT_DEBUG_CHANNEL(haiku_vk); + + + #define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" +@@ -32,6 +39,86 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance + static void *haikudrv_get_vk_device_proc_addr(const char *name); + static void *haikudrv_get_vk_instance_proc_addr(VkInstance instance, const char *name); + ++#define VkCheckRet(err) {VkResult _err = (err); if (_err != VK_SUCCESS) return _err;} ++ ++ ++recursive_lock sDevicesLock = RECURSIVE_LOCK_INITIALIZER("vkDevices"); ++std::map *sDevices; ++ ++ ++static VkPhysicalDevice GetPhysicalDevice(VkDevice dev) ++{ ++ RecursiveLocker lock(&sDevicesLock); ++ if (sDevices == NULL) ++ return NULL; ++ auto it = sDevices->find(dev); ++ if (it == sDevices->end()) ++ return NULL; ++ return it->second; ++} ++ ++static uint32_t getMemoryTypeIndex(VkPhysicalDevice physicalDevice, uint32_t typeBits, VkMemoryPropertyFlags properties) { ++ VkPhysicalDeviceMemoryProperties deviceMemoryProperties; ++ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); ++ for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) { ++ if ((typeBits & 1) == 1) { ++ if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { ++ return i; ++ } ++ } ++ typeBits >>= 1; ++ } ++ return 0; ++} ++ ++static void insertImageMemoryBarrier( ++ VkCommandBuffer cmdbuffer, ++ VkImage image, ++ VkAccessFlags srcAccessMask, ++ VkAccessFlags dstAccessMask, ++ VkImageLayout oldImageLayout, ++ VkImageLayout newImageLayout, ++ VkPipelineStageFlags srcStageMask, ++ VkPipelineStageFlags dstStageMask, ++ VkImageSubresourceRange subresourceRange) ++{ ++ VkImageMemoryBarrier imageMemoryBarrier{ ++ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, ++ .srcAccessMask = srcAccessMask, ++ .dstAccessMask = dstAccessMask, ++ .oldLayout = oldImageLayout, ++ .newLayout = newImageLayout, ++ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, ++ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, ++ .image = image, ++ .subresourceRange = subresourceRange ++ }; ++ ++ vkCmdPipelineBarrier( ++ cmdbuffer, ++ srcStageMask, ++ dstStageMask, ++ 0, ++ 0, nullptr, ++ 0, nullptr, ++ 1, &imageMemoryBarrier ++ ); ++} ++ ++static VkResult submitWork(VkDevice device, VkCommandBuffer cmdBuffer, VkQueue queue) ++{ ++ VkSubmitInfo submitInfo{.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO}; ++ submitInfo.commandBufferCount = 1; ++ submitInfo.pCommandBuffers = &cmdBuffer; ++ VkFenceCreateInfo fenceInfo{.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}; ++ VkFence fence; ++ VkCheckRet(vkCreateFence(device, &fenceInfo, nullptr, &fence)); ++ VkCheckRet(vkQueueSubmit(queue, 1, &submitInfo, fence)); ++ VkCheckRet(vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX)); ++ vkDestroyFence(device, fence, nullptr); ++ return VK_SUCCESS; ++} ++ + + static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, + VkInstanceCreateInfo *dst) +@@ -108,25 +195,570 @@ static const char *wine_vk_native_fn_name(const char *name) + + //#pragma mark - + +-class VKWineSurface { ++class BufferQueue { ++private: ++ ArrayDeleter fItems; ++ int32 fBeg, fLen, fMaxLen; ++ ++public: ++ BufferQueue(int32 maxLen = 0); ++ bool SetMaxLen(int32 maxLen); ++ ++ inline int32 Length() {return fLen;} ++ bool Add(int32 val); ++ int32 Remove(); ++ int32 Begin(); + }; + ++BufferQueue::BufferQueue(int32 maxLen): ++ fItems((maxLen > 0) ? new int32[maxLen] : NULL), ++ fBeg(0), fLen(0), fMaxLen(maxLen) ++{} ++ ++bool BufferQueue::SetMaxLen(int32 maxLen) ++{ ++ if (!(maxLen > 0)) { ++ fItems.Unset(); ++ } else { ++ auto newItems = new(std::nothrow) int32[maxLen]; ++ if (newItems == NULL) ++ return false; ++ fItems.SetTo(newItems); ++ } ++ fMaxLen = maxLen; ++ fBeg = 0; fLen = 0; fMaxLen = maxLen; ++ return true; ++} ++ ++ ++bool BufferQueue::Add(int32 val) ++{ ++ if (!(fLen < fMaxLen)) ++ return false; ++ fItems[(fBeg + fLen)%fMaxLen] = val; ++ fLen++; ++ return true; ++} ++ ++int32 BufferQueue::Remove() ++{ ++ if (!(fLen > 0)) ++ return -1; ++ int32 res = fItems[fBeg%fMaxLen]; ++ fBeg = (fBeg + 1)%fMaxLen; ++ fLen--; ++ return res; ++} ++ ++int32 BufferQueue::Begin() ++{ ++ if (!(fLen > 0)) ++ return -1; ++ return fItems[fBeg%fMaxLen]; ++} ++ ++ ++//#pragma mark - ++ + class VKWineImage { + private: ++ VkDevice fDevice; + VkImage fImage; + VkDeviceMemory fMemory; ++ ++public: ++ VKWineImage(); ++ ~VKWineImage(); ++ VkResult Init(VkDevice device, const VkImageCreateInfo &createInfo, bool cpuMem = false); ++ ++ VkImage ToHandle() {return fImage;} ++ VkDeviceMemory GetMemoryHandle() {return fMemory;} ++}; ++ ++class VKWineSurface { ++private: ++ HWND fHwnd; ++public: ++ VKWineSurface(); ++ ~VKWineSurface(); ++ VkResult Init(VkInstance instance, const VkWin32SurfaceCreateInfoKHR &createInfo); ++ ++ VkResult GetCapabilities(VkPhysicalDevice physDev, VkSurfaceCapabilitiesKHR *capabilities); ++ VkResult GetFormats(VkPhysicalDevice physDev, uint32_t *count, VkSurfaceFormatKHR *formats); ++ VkResult GetPresentModes(VkPhysicalDevice physDev, uint32_t *count, VkPresentModeKHR *modes); ++ VkResult GetPresentRectangles(VkPhysicalDevice physDev, uint32_t* pRectCount, VkRect2D* pRects); ++ ++ static VKWineSurface *FromHandle(VkSurfaceKHR surface) {return (VKWineSurface*)surface;} ++ VkSurfaceKHR ToHandle() {return (VkSurfaceKHR)this;} ++ HWND GetHwnd() {return fHwnd;} + }; + + class VKWineSwapchain { + private: ++ recursive_lock fLock; ++ VkDevice fDevice; ++ VKWineSurface *fSurface; ++ VkExtent2D fImageExtent; ++ uint32 fImageCnt; + ArrayDeleter fImages; ++ BufferQueue fImagePool; ++ ObjectDeleter fBuffer; ++ VkCommandPool fCommandPool; ++ VkQueue fQueue; ++ VkFence fFence; ++ ++ VkImageCreateInfo ImageFromCreateInfo(const VkSwapchainCreateInfoKHR &createInfo); ++ VkResult CreateBuffer(); ++ VkResult CopyToBuffer(VkImage srcImage, int32_t width, int32_t height); + + public: +- VKWineSwapchain(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo); ++ VKWineSwapchain(); ++ ~VKWineSwapchain(); ++ VkResult Init(VkDevice device, const VkSwapchainCreateInfoKHR &createInfo); ++ ++ VkResult GetSwapchainImages(uint32_t *count, VkImage *images); ++ VkResult AcquireNextImage(const VkAcquireNextImageInfoKHR *pAcquireInfo, uint32_t *pImageIndex); ++ VkResult QueuePresent(VkQueue queue, const VkPresentInfoKHR *present_info, uint32_t idx); ++ ++ static VKWineSwapchain *FromHandle(VkSwapchainKHR surface) {return (VKWineSwapchain*)surface;} ++ VkSwapchainKHR ToHandle() {return (VkSwapchainKHR)this;} + }; + + +-//#pragma mark - ++//#pragma mark - VKWineImage ++ ++VKWineImage::VKWineImage(): ++ fDevice(NULL), fImage(0), fMemory(0) ++{} ++ ++VKWineImage::~VKWineImage() ++{ ++ vkFreeMemory(fDevice, fMemory, NULL); ++ vkDestroyImage(fDevice, fImage, NULL); ++} ++ ++VkResult VKWineImage::Init(VkDevice device, const VkImageCreateInfo &createInfo, bool cpuMem) ++{ ++ fDevice = device; ++ ++ VkCheckRet(vkCreateImage(fDevice, &createInfo, NULL, &fImage)); ++ ++ VkMemoryRequirements memRequirements; ++ vkGetImageMemoryRequirements(device, fImage, &memRequirements); ++ size_t memTypeIdx = 0; ++ if (cpuMem) { ++ memTypeIdx = getMemoryTypeIndex(GetPhysicalDevice(fDevice), memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); ++ } else { ++ for (; memTypeIdx < 8 * sizeof(memRequirements.memoryTypeBits); ++memTypeIdx) { ++ if (memRequirements.memoryTypeBits & (1u << memTypeIdx)) ++ break; ++ } ++ assert(memTypeIdx <= 8 * sizeof(memRequirements.memoryTypeBits) - 1); ++ } ++ ++ VkMemoryAllocateInfo memAllocInfo{ ++ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, ++ .allocationSize = memRequirements.size, ++ .memoryTypeIndex = (uint32_t)memTypeIdx ++ }; ++ VkCheckRet(vkAllocateMemory(device, &memAllocInfo, nullptr, &fMemory)); ++ VkCheckRet(vkBindImageMemory(device, fImage, fMemory, 0)); ++ ++ return VK_SUCCESS; ++} ++ ++ ++//#pragma mark - VKWineSurface ++ ++VKWineSurface::VKWineSurface(): ++ fHwnd(NULL) ++{} ++ ++VKWineSurface::~VKWineSurface() ++{} ++ ++VkResult VKWineSurface::Init(VkInstance instance, const VkWin32SurfaceCreateInfoKHR &createInfo) ++{ ++ fHwnd = createInfo.hwnd; ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSurface::GetCapabilities(VkPhysicalDevice physDev, VkSurfaceCapabilitiesKHR *surfaceCapabilities) ++{ ++ /* Image count limits */ ++ surfaceCapabilities->minImageCount = 1; ++ surfaceCapabilities->maxImageCount = 3; ++ ++ /* Surface extents */ ++ surfaceCapabilities->currentExtent = {0xffffffff, 0xffffffff}; ++ surfaceCapabilities->minImageExtent = {1, 1}; ++ /* Ask the device for max */ ++ VkPhysicalDeviceProperties devProps; ++ vkGetPhysicalDeviceProperties(physDev, &devProps); ++ ++ surfaceCapabilities->maxImageExtent = { ++ devProps.limits.maxImageDimension2D, devProps.limits.maxImageDimension2D ++ }; ++ surfaceCapabilities->maxImageArrayLayers = 1; ++ ++ /* Surface transforms */ ++ surfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; ++ surfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; ++ ++ /* Composite alpha */ ++ surfaceCapabilities->supportedCompositeAlpha = (VkCompositeAlphaFlagBitsKHR)( ++ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | ++ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR ++ ); ++ ++ /* Image usage flags */ ++ surfaceCapabilities->supportedUsageFlags = ++ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | ++ VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; ++ ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSurface::GetFormats(VkPhysicalDevice physDev, uint32_t *count, VkSurfaceFormatKHR *surfaceFormats) ++{ ++/* ++ VkFormat formats[] = {VK_FORMAT_B8G8R8A8_UNORM}; ++ uint32_t formatCnt = 1; ++*/ ++ constexpr int max_core_1_0_formats = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1; ++ VkFormat formats[max_core_1_0_formats]; ++ uint32_t formatCnt = 0; ++ ++ for (int format = 0; format < max_core_1_0_formats; format++) { ++ VkImageFormatProperties formatProps; ++ VkResult res = vkGetPhysicalDeviceImageFormatProperties( ++ physDev, (VkFormat)format, VK_IMAGE_TYPE_2D, ++ VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, ++ &formatProps ++ ); ++ if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) { ++ formats[formatCnt++] = (VkFormat)format; ++ } ++ } ++ ++ if (surfaceFormats == NULL) { ++ *count = formatCnt; ++ return VK_SUCCESS; ++ } ++ memcpy(surfaceFormats, formats, sizeof(VkFormat)*std::min(*count, formatCnt)); ++ if (*count < formatCnt) ++ return VK_INCOMPLETE; ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSurface::GetPresentModes(VkPhysicalDevice physDev, uint32_t *count, VkPresentModeKHR *presentModes) ++{ ++ static const VkPresentModeKHR modes[] = {VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR}; ++ if (presentModes == NULL) { ++ *count = B_COUNT_OF(modes); ++ return VK_SUCCESS; ++ } ++ memcpy(presentModes, modes, sizeof(VkPresentModeKHR)*std::min(*count, B_COUNT_OF(modes))); ++ if (*count < B_COUNT_OF(modes)) ++ return VK_INCOMPLETE; ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSurface::GetPresentRectangles(VkPhysicalDevice physDev, uint32_t* pRectCount, VkRect2D* pRects) ++{ ++ if (pRects == NULL) { ++ *pRectCount = 1; ++ return VK_SUCCESS; ++ } ++ if (*pRectCount < 1) { ++ return VK_INCOMPLETE; ++ } ++ VkSurfaceCapabilitiesKHR caps; ++ VkCheckRet(GetCapabilities(physDev, &caps)); ++ pRects[0].offset.x = 0; ++ pRects[0].offset.y = 0; ++ pRects[0].extent = caps.currentExtent; ++ return VK_SUCCESS; ++} ++ ++ ++//#pragma mark - VKWineSwapchain ++ ++VKWineSwapchain::VKWineSwapchain(): ++ fLock(RECURSIVE_LOCK_INITIALIZER("VKWineSwapchain")), ++ fCommandPool(VK_NULL_HANDLE), ++ fFence(VK_NULL_HANDLE) ++{} ++ ++VKWineSwapchain::~VKWineSwapchain() ++{ ++ if (fCommandPool != VK_NULL_HANDLE) { ++ vkDestroyCommandPool(fDevice, fCommandPool, nullptr); ++ vkQueueWaitIdle(fQueue); ++ } ++ ++ vkDestroyFence(fDevice, fFence, NULL); ++ recursive_lock_destroy(&fLock); ++} ++ ++VkImageCreateInfo VKWineSwapchain::ImageFromCreateInfo(const VkSwapchainCreateInfoKHR &createInfo) ++{ ++ return VkImageCreateInfo{ ++ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, ++ .pNext = nullptr, ++ .imageType = VK_IMAGE_TYPE_2D, ++ .format = createInfo.imageFormat, ++ .extent = { ++ createInfo.imageExtent.width, ++ createInfo.imageExtent.height, ++ 1 ++ }, ++ .mipLevels = 1, ++ .arrayLayers = createInfo.imageArrayLayers, ++ .samples = VK_SAMPLE_COUNT_1_BIT, ++ .tiling = VK_IMAGE_TILING_OPTIMAL, ++ .usage = createInfo.imageUsage, ++ .sharingMode = createInfo.imageSharingMode, ++ .queueFamilyIndexCount = createInfo.queueFamilyIndexCount, ++ .pQueueFamilyIndices = createInfo.pQueueFamilyIndices, ++ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ++ }; ++} ++ ++VkResult VKWineSwapchain::CreateBuffer() ++{ ++ VkCommandPoolCreateInfo cmdPoolInfo{ ++ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, ++ .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, ++ .queueFamilyIndex = 0 ++ }; ++ VkCheckRet(vkCreateCommandPool(fDevice, &cmdPoolInfo, nullptr, &fCommandPool)); ++ ++ VkImageCreateInfo createInfo{ ++ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, ++ .imageType = VK_IMAGE_TYPE_2D, ++ .format = VK_FORMAT_R8G8B8A8_UNORM, ++ .extent = { ++ .width = fImageExtent.width, ++ .height = fImageExtent.height, ++ .depth = 1 ++ }, ++ .mipLevels = 1, ++ .arrayLayers = 1, ++ .samples = VK_SAMPLE_COUNT_1_BIT, ++ .tiling = VK_IMAGE_TILING_LINEAR, ++ .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, ++ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ++ }; ++ fBuffer.SetTo(new(std::nothrow) VKWineImage()); ++ if (!fBuffer.IsSet()) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ VkCheckRet(fBuffer->Init(fDevice, createInfo, true)); ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSwapchain::CopyToBuffer(VkImage srcImage, int32_t width, int32_t height) ++{ ++ // Do the actual blit from the offscreen image to our host visible destination image ++ VkCommandBufferAllocateInfo cmdBufAllocateInfo{ ++ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, ++ .commandPool = fCommandPool, ++ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, ++ .commandBufferCount = 1 ++ }; ++ VkCommandBuffer copyCmd; ++ VkCheckRet(vkAllocateCommandBuffers(fDevice, &cmdBufAllocateInfo, ©Cmd)); ++ VkCommandBufferBeginInfo cmdBufInfo{.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; ++ VkCheckRet(vkBeginCommandBuffer(copyCmd, &cmdBufInfo)); ++ ++ // Transition destination image to transfer destination layout ++ insertImageMemoryBarrier( ++ copyCmd, ++ fBuffer->ToHandle(), ++ 0, ++ VK_ACCESS_TRANSFER_WRITE_BIT, ++ VK_IMAGE_LAYOUT_UNDEFINED, ++ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, ++ VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } ++ ); ++ ++ // srcImage is already in VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, and does not need to be transitioned ++ ++ VkImageCopy imageCopyRegion{}; ++ imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ++ imageCopyRegion.srcSubresource.layerCount = 1; ++ imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ++ imageCopyRegion.dstSubresource.layerCount = 1; ++ imageCopyRegion.extent.width = width; ++ imageCopyRegion.extent.height = height; ++ imageCopyRegion.extent.depth = 1; ++ ++ vkCmdCopyImage( ++ copyCmd, ++ srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, ++ fBuffer->ToHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ++ 1, ++ &imageCopyRegion ++ ); ++ ++ // Transition destination image to general layout, which is the required layout for mapping the image memory later on ++ insertImageMemoryBarrier( ++ copyCmd, ++ fBuffer->ToHandle(), ++ VK_ACCESS_TRANSFER_WRITE_BIT, ++ VK_ACCESS_MEMORY_READ_BIT, ++ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ++ VK_IMAGE_LAYOUT_GENERAL, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, ++ VK_PIPELINE_STAGE_TRANSFER_BIT, ++ VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} ++ ); ++ ++ VkCheckRet(vkEndCommandBuffer(copyCmd)); ++ ++ VkCheckRet(submitWork(fDevice, copyCmd, fQueue)); ++ vkFreeCommandBuffers(fDevice, fCommandPool, 1, ©Cmd); ++ ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSwapchain::Init(VkDevice device, const VkSwapchainCreateInfoKHR &createInfo) ++{ ++ fDevice = device; ++ fSurface = VKWineSurface::FromHandle(createInfo.surface); ++ ++ VkFenceCreateInfo fence_info{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0}; ++ VkCheckRet(vkCreateFence(fDevice, &fence_info, NULL, &fFence)); ++ ++ fImageExtent.width = createInfo.imageExtent.width; ++ fImageExtent.height = createInfo.imageExtent.height; ++ ++ VkImageCreateInfo imageCreateInfo = ImageFromCreateInfo(createInfo); ++ ++ fImageCnt = createInfo.minImageCount; ++ fImages.SetTo(new(std::nothrow) VKWineImage[fImageCnt]); ++ if (!fImages.IsSet()) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ if(!fImagePool.SetMaxLen(fImageCnt)) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ ++ for (uint32_t i = 0; i < fImageCnt; i++) { ++ VkCheckRet(fImages[i].Init(device, imageCreateInfo)); ++ fImagePool.Add(i); ++ } ++ ++ vkGetDeviceQueue(device, 0, 0, &fQueue); ++ //VkCheckRet(vkSetDeviceLoaderData(device, fQueue)); ++ ++ VkCheckRet(CreateBuffer()); ++ ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSwapchain::GetSwapchainImages(uint32_t *count, VkImage *images) ++{ ++ if (images == NULL) { ++ *count = fImageCnt; ++ return VK_SUCCESS; ++ } ++ uint32_t copyCnt = std::min(*count, fImageCnt); ++ for (uint32_t i = 0; i < copyCnt; i++) { ++ images[i] = fImages[i].ToHandle(); ++ } ++ if (*count < fImageCnt) ++ return VK_INCOMPLETE; ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSwapchain::AcquireNextImage(const VkAcquireNextImageInfoKHR *pAcquireInfo, uint32_t *pImageIndex) ++{ ++ int32 imageIdx; ++ for(;;) { ++ recursive_lock_lock(&fLock); ++ imageIdx = fImagePool.Remove(); ++ recursive_lock_unlock(&fLock); ++ if (imageIdx < 0) { ++ snooze(100); ++ continue; ++ } ++ break; ++ }; ++ *pImageIndex = imageIdx; ++ ++ if (VK_NULL_HANDLE != pAcquireInfo->semaphore || VK_NULL_HANDLE != pAcquireInfo->fence) { ++ VkSubmitInfo submit = {VK_STRUCTURE_TYPE_SUBMIT_INFO}; ++ ++ if (VK_NULL_HANDLE != pAcquireInfo->semaphore) { ++ submit.signalSemaphoreCount = 1; ++ submit.pSignalSemaphores = &pAcquireInfo->semaphore; ++ } ++ ++ submit.commandBufferCount = 0; ++ submit.pCommandBuffers = nullptr; ++ VkResult retval = vkQueueSubmit(fQueue, 1, &submit, pAcquireInfo->fence); ++ assert(retval == VK_SUCCESS); ++ } ++ ++ return VK_SUCCESS; ++} ++ ++VkResult VKWineSwapchain::QueuePresent(VkQueue queue, const VkPresentInfoKHR *presentInfo, uint32_t idx) ++{ ++ vkResetFences(fDevice, 1, &fFence); ++ VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; ++ ++ VkSubmitInfo submit_info = { ++ VK_STRUCTURE_TYPE_SUBMIT_INFO, NULL, presentInfo->waitSemaphoreCount, presentInfo->pWaitSemaphores, &pipeline_stage_flags, 0, NULL, 0, NULL ++ }; ++ ++ VkResult result = vkQueueSubmit(queue, 1, &submit_info, fFence); ++ if (result == VK_SUCCESS) { ++ vkWaitForFences(fDevice, 1, &fFence, VK_TRUE, 100000000000); ++ } ++ ++ recursive_lock_lock(&fLock); ++ uint32_t imageIdx = presentInfo->pImageIndices[idx]; ++ ++ CopyToBuffer(fImages[imageIdx].ToHandle(), fImageExtent.width, fImageExtent.height); ++ VKWineImage &srcImage = *fBuffer.Get(); ++ ++ VkImageSubresource subResource{ ++ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ++ }; ++ VkSubresourceLayout subResourceLayout; ++ vkGetImageSubresourceLayout(fDevice, srcImage.ToHandle(), &subResource, &subResourceLayout); ++ size_t stride = subResourceLayout.rowPitch; ++ ++ char *imagedata = NULL; ++ vkMapMemory(fDevice, srcImage.GetMemoryHandle(), 0, VK_WHOLE_SIZE, 0, (void**)&imagedata); ++ imagedata += subResourceLayout.offset; ++ ++ HDC hdc = GetDC(fSurface->GetHwnd()); ++ BITMAPINFO bitmapInfo{ ++ .bmiHeader = { ++ .biSize = sizeof(BITMAPINFOHEADER), ++ .biWidth = (LONG)(stride/4), ++ .biHeight = -(LONG)fImageExtent.height, ++ .biPlanes = 1, ++ .biBitCount = 32, ++ .biCompression = BI_RGB, ++ .biSizeImage = (DWORD)(stride*fImageExtent.height) ++ } ++ }; ++ SetDIBitsToDevice(hdc, 0, 0, fImageExtent.width, fImageExtent.height, 0, 0, 0, fImageExtent.height, imagedata, &bitmapInfo, DIB_RGB_COLORS); ++ ReleaseDC(fSurface->GetHwnd(), hdc); ++ ++ vkUnmapMemory(fDevice, srcImage.GetMemoryHandle()); ++ ++ fImagePool.Add(imageIdx); ++ recursive_lock_unlock(&fLock); ++ return VK_SUCCESS; ++} ++ ++ ++//#pragma mark - Instance + + static VkResult haikudrv_vkCreateInstance(const VkInstanceCreateInfo *create_info, + const VkAllocationCallbacks *allocator, VkInstance *instance) +@@ -155,46 +787,12 @@ static VkResult haikudrv_vkCreateInstance(const VkInstanceCreateInfo *create_inf + return res; + } + +-static VkResult haikudrv_vkCreateSwapchainKHR(VkDevice device, +- const VkSwapchainCreateInfoKHR *create_info, +- const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain) +-{ +- TRACE("()\n"); +- return vkCreateSwapchainKHR(device, create_info, allocator, swapchain); +-} +- +-static VkResult haikudrv_vkCreateWin32SurfaceKHR(VkInstance instance, +- const VkWin32SurfaceCreateInfoKHR *create_info, +- const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) +-{ +- TRACE("()\n"); +- PFN_vkCreateHeadlessSurfaceEXT proc = (PFN_vkCreateHeadlessSurfaceEXT) +- vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"); +- VkHeadlessSurfaceCreateInfoEXT surfaceCreateInfo = {}; +- surfaceCreateInfo.sType = (VkStructureType)VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT; +- return proc(instance, &surfaceCreateInfo, allocator, surface); +-} +- + static void haikudrv_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator) + { + TRACE("()\n"); + vkDestroyInstance(instance, allocator); + } + +-static void haikudrv_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, +- const VkAllocationCallbacks *allocator) +-{ +- TRACE("()\n"); +- vkDestroySurfaceKHR(instance, surface, allocator); +-} +- +-static void haikudrv_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, +- const VkAllocationCallbacks *allocator) +-{ +- TRACE("()\n"); +- vkDestroySwapchainKHR(device, swapchain, allocator); +-} +- + static VkResult haikudrv_vkEnumerateInstanceExtensionProperties(const char *layer_name, + uint32_t *count, VkExtensionProperties* properties) + { +@@ -281,66 +879,123 @@ static void *haikudrv_vkGetInstanceProcAddr(VkInstance instance, const char *nam + return (void*)vkGetInstanceProcAddr(instance, name); + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev, +- const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities) ++static VkResult VKAPI_CALL haikudrv_vkCreateDevice( ++ VkPhysicalDevice physicalDevice, ++ const VkDeviceCreateInfo* pCreateInfo, ++ const VkAllocationCallbacks* pAllocator, ++ VkDevice* pDevice) ++{ ++ TRACE("()\n"); ++ VkCheckRet(vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice)); ++ ++ RecursiveLocker lock(&sDevicesLock); ++ if (sDevices == NULL) { ++ sDevices = new std::map(); ++ } ++ sDevices->emplace(*pDevice, physicalDevice); ++ ++ return VK_SUCCESS; ++} ++ ++static void VKAPI_CALL haikudrv_vkDestroyDevice( ++ VkDevice device, ++ const VkAllocationCallbacks* pAllocator) ++{ ++ TRACE("()\n"); ++ ++ { ++ RecursiveLocker lock(&sDevicesLock); ++ auto it = sDevices->find(device); ++ sDevices->erase(it); ++ } ++ ++ vkDestroyDevice(device, pAllocator); ++} ++ ++//#pragma mark - Surface ++ ++static VkResult haikudrv_vkCreateWin32SurfaceKHR(VkInstance instance, ++ const VkWin32SurfaceCreateInfoKHR *createInfo, ++ const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface) ++{ ++ TRACE("()\n"); ++ ++ auto wineSurface = new(std::nothrow) VKWineSurface(); ++ if (wineSurface == NULL) ++ return VK_ERROR_OUT_OF_HOST_MEMORY; ++ VkCheckRet(wineSurface->Init(instance, *createInfo)); ++ *surface = wineSurface->ToHandle(); ++ return VK_SUCCESS; ++} ++ ++static void haikudrv_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *allocator) + { + TRACE("()\n"); +- return vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, surface_info, capabilities); ++ delete VKWineSurface::FromHandle(surface); + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev, ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physDev, ++ const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities) ++{ ++ ERR("(): not implemented\n"); ++ return VK_NOT_READY; ++} ++ ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physDev, + VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities) + { + TRACE("()\n"); +- return vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface, capabilities); ++ return VKWineSurface::FromHandle(surface)->GetCapabilities(physDev, capabilities); + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev, ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physDev, + const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, uint32_t *count, VkSurfaceFormat2KHR *formats) + { +- TRACE("()\n"); +- return vkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, surface_info, count, formats); ++ ERR("(): not implemented\n"); ++ return VK_NOT_READY; + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physDev, + VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats) + { + TRACE("()\n"); +- return vkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface, count, formats); ++ return VKWineSurface::FromHandle(surface)->GetFormats(physDev, count, formats); + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev, ++static VkResult haikudrv_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physDev, + VkSurfaceKHR surface, uint32_t *count, VkPresentModeKHR *modes) + { + TRACE("()\n"); +- return vkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev, surface, count, modes); ++ return VKWineSurface::FromHandle(surface)->GetPresentModes(physDev, count, modes); + } + +-static VkResult haikudrv_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev, ++static VkResult haikudrv_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physDev, + uint32_t index, VkSurfaceKHR surface, VkBool32 *supported) + { + TRACE("()\n"); +- return vkGetPhysicalDeviceSurfaceSupportKHR(phys_dev, index, surface, supported); ++ *supported = VK_TRUE; ++ return VK_SUCCESS; + } + +-static VkBool32 haikudrv_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, +- uint32_t index) ++static VkBool32 haikudrv_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physDev, uint32_t index) + { + TRACE("()\n"); + return VK_TRUE; + } + +-static VkResult haikudrv_vkGetSwapchainImagesKHR(VkDevice device, +- VkSwapchainKHR swapchain, uint32_t *count, VkImage *images) +-{ ++static VkResult VKAPI_CALL haikudrv_vkGetDeviceGroupSurfacePresentModesKHR( ++ VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR *pModes ++) { + TRACE("()\n"); +- return vkGetSwapchainImagesKHR(device, swapchain, count, images); ++ *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR; ++ return VK_SUCCESS; + } + +-static VkResult haikudrv_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info) +-{ ++static VkResult VKAPI_CALL haikudrv_vkGetPhysicalDevicePresentRectanglesKHR( ++ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects ++) { + TRACE("()\n"); +- return vkQueuePresentKHR(queue, present_info); ++ return VKWineSurface::FromHandle(surface)->GetPresentRectangles(physicalDevice, pRectCount, pRects); + } + + static VkSurfaceKHR haikudrv_wine_get_native_surface(VkSurfaceKHR surface) +@@ -350,6 +1005,68 @@ static VkSurfaceKHR haikudrv_wine_get_native_surface(VkSurfaceKHR surface) + } + + ++//#pragma mark - Swapchain ++ ++static VkResult haikudrv_vkCreateSwapchainKHR(VkDevice device, ++ const VkSwapchainCreateInfoKHR *createInfo, ++ const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain) ++{ ++ TRACE("()\n"); ++ auto wineSwapchain = new(std::nothrow) VKWineSwapchain(); ++ if (wineSwapchain == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY; ++ VkCheckRet(wineSwapchain->Init(device, *createInfo)); ++ *swapchain = wineSwapchain->ToHandle(); ++ return VK_SUCCESS; ++} ++ ++static void haikudrv_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *allocator) ++{ ++ TRACE("()\n"); ++ delete VKWineSwapchain::FromHandle(swapchain); ++} ++ ++static VkResult haikudrv_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *count, VkImage *images) ++{ ++ TRACE("()\n"); ++ return VKWineSwapchain::FromHandle(swapchain)->GetSwapchainImages(count, images); ++} ++ ++static VkResult haikudrv_vkAcquireNextImageKHR( ++ VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex ++) { ++ TRACE("()\n"); ++ VkAcquireNextImageInfoKHR info{ ++ .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR, ++ .swapchain = swapchain, ++ .timeout = timeout, ++ .semaphore = semaphore, ++ .fence = fence ++ }; ++ return VKWineSwapchain::FromHandle(swapchain)->AcquireNextImage(&info, pImageIndex); ++} ++ ++static VkResult haikudrv_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) ++{ ++ TRACE("()\n"); ++ ++ VkResult ret = VK_SUCCESS; ++ for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { ++ auto *sc = VKWineSwapchain::FromHandle(pPresentInfo->pSwapchains[i]); ++ VkResult res = sc->QueuePresent(queue, pPresentInfo, i); ++ ++ if (pPresentInfo->pResults != nullptr) ++ pPresentInfo->pResults[i] = res; ++ ++ if (res != VK_SUCCESS && ret == VK_SUCCESS) ++ ret = res; ++ } ++ ++ return ret; ++} ++ ++ ++//#pragma mark - ++ + #define VULKAN_HOOK(name) .p_##name = haikudrv_##name + static const struct vulkan_funcs vulkan_funcs = + { +@@ -360,10 +1077,10 @@ static const struct vulkan_funcs vulkan_funcs = + VULKAN_HOOK(vkDestroySurfaceKHR), + VULKAN_HOOK(vkDestroySwapchainKHR), + VULKAN_HOOK(vkEnumerateInstanceExtensionProperties), +- // vkGetDeviceGroupSurfacePresentModesKHR ++ VULKAN_HOOK(vkGetDeviceGroupSurfacePresentModesKHR), + VULKAN_HOOK(vkGetDeviceProcAddr), + VULKAN_HOOK(vkGetInstanceProcAddr), +- // vkGetPhysicalDevicePresentRectanglesKHR ++ VULKAN_HOOK(vkGetPhysicalDevicePresentRectanglesKHR), + VULKAN_HOOK(vkGetPhysicalDeviceSurfaceCapabilities2KHR), + VULKAN_HOOK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR), + VULKAN_HOOK(vkGetPhysicalDeviceSurfaceFormats2KHR), +@@ -381,12 +1098,18 @@ static const struct vulkan_funcs vulkan_funcs = + static void *haikudrv_get_vk_device_proc_addr(const char *name) + { + TRACE("(\"%s\")\n", name); ++ if (strcmp(name, "vkAcquireNextImageKHR") == 0) ++ return (void*)haikudrv_vkAcquireNextImageKHR; ++ if (strcmp(name, "vkDestroyDevice") == 0) ++ return (void*)haikudrv_vkDestroyDevice; + return get_vulkan_driver_device_proc_addr(&vulkan_funcs, name); + } + + static void *haikudrv_get_vk_instance_proc_addr(VkInstance instance, const char *name) + { + TRACE("(\"%s\")\n", name); ++ if (strcmp(name, "vkCreateDevice") == 0) ++ return (void*)haikudrv_vkCreateDevice; + return get_vulkan_driver_instance_proc_addr(&vulkan_funcs, instance, name); + } + +-- +2.30.2 + + +From 619fb2083a29685c115014d3e45b5b00cf285992 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Thu, 20 Jan 2022 22:28:58 +0900 +Subject: winehaiku.drv: update + +--- + dlls/winehaiku.drv/Makefile.in | 2 +- + dlls/winehaiku.drv/{mouse.c => mouse.cpp} | 22 +++++++- + dlls/winehaiku.drv/window.cpp | 60 ++-------------------- + dlls/winehaiku.drv/window.h | 62 +++++++++++++++++++++++ + 4 files changed, 86 insertions(+), 60 deletions(-) + rename dlls/winehaiku.drv/{mouse.c => mouse.cpp} (85%) + create mode 100644 dlls/winehaiku.drv/window.h + +diff --git a/dlls/winehaiku.drv/Makefile.in b/dlls/winehaiku.drv/Makefile.in +index 6a8d910ed66..2e0d0232fa5 100644 +--- a/dlls/winehaiku.drv/Makefile.in ++++ b/dlls/winehaiku.drv/Makefile.in +@@ -13,7 +13,7 @@ C_SRCS = \ + ime.c \ + init.c \ + keyboard.c \ +- mouse.c \ ++ mouse.cpp \ + settings.cpp \ + systray.c \ + window.cpp \ +diff --git a/dlls/winehaiku.drv/mouse.c b/dlls/winehaiku.drv/mouse.cpp +similarity index 85% +rename from dlls/winehaiku.drv/mouse.c +rename to dlls/winehaiku.drv/mouse.cpp +index b44039e9d76..cbf4eaafff6 100644 +--- a/dlls/winehaiku.drv/mouse.c ++++ b/dlls/winehaiku.drv/mouse.cpp +@@ -25,7 +25,11 @@ + #include + #include + ++#define thread_info haiku_thread_info ++#include ++#undef thread_info + ++extern "C" { + #define NONAMELESSUNION + #define OEMRESOURCE + #include "windef.h" +@@ -36,6 +40,8 @@ + #include "wine/server.h" + #include "wine/unicode.h" + #include "wine/debug.h" ++} ++ + + WINE_DEFAULT_DEBUG_CHANNEL(cursor); + +@@ -59,7 +65,11 @@ void CDECL HAIKUDRV_SetCursor( HCURSOR handle ) + */ + BOOL CDECL HAIKUDRV_SetCursorPos( INT x, INT y ) + { +- return TRUE; ++/* ++ ERR("(%d, %d)\n", x, y); ++ set_mouse_position(x, y); ++ return TRUE; ++*/ + } + + /*********************************************************************** +@@ -67,7 +77,15 @@ BOOL CDECL HAIKUDRV_SetCursorPos( INT x, INT y ) + */ + BOOL CDECL HAIKUDRV_GetCursorPos(LPPOINT pos) + { +- return TRUE; ++/* ++ ERR("()\n"); ++ BPoint haikuPos; ++ if (get_mouse(&haikuPos, NULL) < B_OK) ++ return FALSE; ++ pos->x = haikuPos.x; ++ pos->y = haikuPos.y; ++*/ ++ return TRUE; + } + + /*********************************************************************** +diff --git a/dlls/winehaiku.drv/window.cpp b/dlls/winehaiku.drv/window.cpp +index 26667b2ad0c..18dcba70c69 100644 +--- a/dlls/winehaiku.drv/window.cpp ++++ b/dlls/winehaiku.drv/window.cpp +@@ -29,19 +29,11 @@ + # include + #endif + +-#define thread_info haiku_thread_info + +-#include +-#include +-#include +-#include +-#include ++#include "window.h" ++ + #include +-#include + #include +-#include +- +-#undef thread_info + + #include + +@@ -241,52 +233,6 @@ static void MapKey(char *&chars, size_t &len, int32 key, uint32 modifiers) + + //#pragma mark - + +-class WineView: public BView { +-private: +- HWND fHwnd; +- struct haikudrv_thread_data *fData; +- BBitmap *fBitmap; +- uint32 fOldMouseBtns; +- +-public: +- WineView(HWND hwnd, struct haikudrv_thread_data *data, BRect frame, const char *name); +- void UpdateBitmap(BBitmap *bitmap, BRect dirty); +- void MessageReceived(BMessage *msg); +- +-}; +- +-class WineWindow: public BWindow { +-private: +- WineView *fView; +- HWND fHwnd; +- struct haikudrv_thread_data *fData; +- +-public: +- mutex fCreateMutex; +- window_surface *fSurface; +- bool fSendResizeEvents; +- bool fInDestroy; +- RECT fNonClient; +- //HANDLE fEvent; +- +- WineWindow(HWND hwnd, struct haikudrv_thread_data *data, BRect frame); +- virtual ~WineWindow(); +- +- bool QuitRequested() override; +- +- void FrameMoved(BPoint newPosition) override; +- void FrameResized(float newWidth, float newHeight) override; +- +- HWND Handle() {return fHwnd;} +- WineView *View() {return fView;} +-}; +- +-class WineApplication: public BApplication { +-public: +- WineApplication(); +-}; +- +- + WineView::WineView(HWND hwnd, struct haikudrv_thread_data *data, BRect frame, const char *name): + BView(frame, name, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE), + fHwnd(hwnd), +@@ -570,7 +516,7 @@ static UINT CALLBACK WindowThread(void *arg) + return 0; + } + +-static WineWindow* HaikuThisWindow(HWND hwnd, bool create = true) ++WineWindow* HaikuThisWindow(HWND hwnd, bool create) + { + BAutolock lock(be_app); + auto it = sWindows->find(hwnd); +diff --git a/dlls/winehaiku.drv/window.h b/dlls/winehaiku.drv/window.h +new file mode 100644 +index 00000000000..dc737c38fa3 +--- /dev/null ++++ b/dlls/winehaiku.drv/window.h +@@ -0,0 +1,62 @@ ++#pragma once ++ ++#define thread_info haiku_thread_info ++#include ++#include ++#include ++#include ++#include ++#undef thread_info ++ ++extern "C" { ++#include "haikudrv.h" ++} ++#undef GetMonitorInfo ++ ++class WineView: public BView { ++private: ++ HWND fHwnd; ++ struct haikudrv_thread_data *fData; ++ BBitmap *fBitmap; ++ uint32 fOldMouseBtns; ++ ++public: ++ WineView(HWND hwnd, struct haikudrv_thread_data *data, BRect frame, const char *name); ++ void UpdateBitmap(BBitmap *bitmap, BRect dirty); ++ void MessageReceived(BMessage *msg); ++ ++}; ++ ++class WineWindow: public BWindow { ++private: ++ WineView *fView; ++ HWND fHwnd; ++ struct haikudrv_thread_data *fData; ++ ++public: ++ mutex fCreateMutex; ++ window_surface *fSurface; ++ bool fSendResizeEvents; ++ bool fInDestroy; ++ RECT fNonClient; ++ //HANDLE fEvent; ++ ++ WineWindow(HWND hwnd, struct haikudrv_thread_data *data, BRect frame); ++ virtual ~WineWindow(); ++ ++ bool QuitRequested() override; ++ ++ void FrameMoved(BPoint newPosition) override; ++ void FrameResized(float newWidth, float newHeight) override; ++ ++ HWND Handle() {return fHwnd;} ++ WineView *View() {return fView;} ++}; ++ ++class WineApplication: public BApplication { ++public: ++ WineApplication(); ++}; ++ ++ ++WineWindow* HaikuThisWindow(HWND hwnd, bool create = true); +-- +2.30.2 + + +From 084d7361e7c331d191d3b523a65f5af0f7070767 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Thu, 20 Jan 2022 22:31:14 +0900 +Subject: haiku: update + +--- + dlls/ntdll/unix/signal_x86_64.c | 64 +++++++++++++++++++++++++++++++-- + dlls/ntdll/unix/virtual.c | 7 ++++ + dlls/winex11.drv/keyboard.c | 4 +-- + dlls/winex11.drv/x11drv_main.c | 3 +- + dlls/ws2_32/unixlib.c | 1 + + programs/winedbg/winedbg.c | 2 ++ + server/fd.c | 1 + + server/signal.c | 3 ++ + tools/winegcc/winegcc.c | 3 ++ + 9 files changed, 82 insertions(+), 6 deletions(-) + +diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c +index 957f796444b..063892046e1 100644 +--- a/dlls/ntdll/unix/signal_x86_64.c ++++ b/dlls/ntdll/unix/signal_x86_64.c +@@ -254,7 +254,7 @@ __ASM_GLOBAL_FUNC( alloc_fs_sel, + #define R13_sig(context) ((context)->uc_mcontext.r13) + #define R14_sig(context) ((context)->uc_mcontext.r14) + #define R15_sig(context) ((context)->uc_mcontext.r15) +-#define CS_sig(context) NULL ++#define CS_sig(context) cs64_sel + #define FS_sig(context) NULL + #define GS_sig(context) NULL + #define EFL_sig(context) ((context)->uc_mcontext.rflags) +@@ -2577,6 +2577,46 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext ) + } + + ++NTSTATUS static LdrFindEntryForAddress2( const void *addr, PLDR_DATA_TABLE_ENTRY *pmod ) ++{ ++ PLIST_ENTRY mark, entry; ++ PLDR_DATA_TABLE_ENTRY mod; ++ ++ mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList; ++ for (entry = mark->Flink; entry != mark; entry = entry->Flink) ++ { ++ mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); ++ if (mod->DllBase <= addr && ++ (const char *)addr < (char*)mod->DllBase + mod->SizeOfImage) ++ { ++ *pmod = mod; ++ return STATUS_SUCCESS; ++ } ++ } ++ return STATUS_NO_MORE_ENTRIES; ++} ++ ++static void WriteRtlString(UNICODE_STRING str) ++{ ++ for (int i = 0; i < str.Length; i++) { ++ printf("%c", str.Buffer[i]); ++ } ++} ++ ++static void WriteModuleName(addr_t address) ++{ ++ HMODULE hModule = NULL; ++ PLDR_DATA_TABLE_ENTRY pmod = NULL; ++ LdrFindEntryForAddress2( ++ (void*)address, ++ &pmod ++ ); ++ hModule = pmod == NULL ? NULL : pmod->DllBase; ++ printf(" hModule: %p\n", hModule); ++ if (hModule != NULL) ++ printf(" BaseDllName: %s\n", debugstr_w(pmod->BaseDllName.Buffer)); printf("\n"); ++} ++ + /********************************************************************** + * segv_handler + * +@@ -2588,11 +2628,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) + struct xcontext context; + ucontext_t *ucontext = sigcontext; + printf("segv_handler\n"); ++ printf("&segv_handler: %p\n", &segv_handler); ++ printf("pKiUserExceptionDispatcher: %p\n", pKiUserExceptionDispatcher); ++ printf(" thread: %" PRId32 "\n", find_thread(NULL)); + printf(" IP: %#" PRIx64 "\n", RIP_sig(ucontext)); + printf(" SP: %#" PRIx64 "\n", RSP_sig(ucontext)); + printf(" FP: %#" PRIx64 "\n", RBP_sig(ucontext)); + printf(" address: %#" PRIx64 "\n", siginfo->si_addr); +- _exit(1); ++ WriteModuleName(RIP_sig(ucontext)); ++ fgetc(stdin); ++ //_exit(1); + + rec.ExceptionAddress = (void *)RIP_sig(ucontext); + save_context( &context, sigcontext ); +@@ -2781,6 +2826,18 @@ static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext ) + */ + static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) + { ++ ucontext_t *ucontext = sigcontext; ++ printf("abrt_handler\n"); ++ printf("&abrt_handler: %p\n", &segv_handler); ++ printf("pKiUserExceptionDispatcher: %p\n", pKiUserExceptionDispatcher); ++ printf(" thread: %" PRId32 "\n", find_thread(NULL)); ++ printf(" IP: %#" PRIx64 "\n", RIP_sig(ucontext)); ++ printf(" SP: %#" PRIx64 "\n", RSP_sig(ucontext)); ++ printf(" FP: %#" PRIx64 "\n", RBP_sig(ucontext)); ++ printf(" address: %#" PRIx64 "\n", siginfo->si_addr); ++ //fgetc(stdin); ++ //_exit(1); ++ + EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE }; + + setup_exception( sigcontext, &rec ); +@@ -2807,7 +2864,7 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext ) + static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext ) + { + struct xcontext context; +- ++//#ifndef __HAIKU__ + if (is_inside_syscall( ucontext )) + { + DECLSPEC_ALIGN(64) XSTATE xs; +@@ -2824,6 +2881,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext ) + wait_suspend( &context.c ); + restore_context( &context, ucontext ); + } ++//#endif + } + + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index 5873a3e2335..ca6bb6caceb 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -22,6 +22,12 @@ + #pragma makedep unix + #endif + ++#define cpu_info haiku_cpu_info ++#if defined(__HAIKU__) ++# include ++#endif ++#undef cpu_info ++ + #include "config.h" + + #include +@@ -3164,6 +3170,7 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SI + + if (!reserve_size) reserve_size = main_image_info.MaximumStackSize; + if (!commit_size) commit_size = main_image_info.CommittedStackSize; ++ commit_size = reserve_size; + + size = max( reserve_size, commit_size ); + if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */ +diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c +index c6eab6f5cfa..9086a9db8cb 100644 +--- a/dlls/winex11.drv/keyboard.c ++++ b/dlls/winex11.drv/keyboard.c +@@ -2132,7 +2132,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize) + int keyi; + KeySym keys; + char *name; +- ++#if 0 + scanCode = lParam >> 16; + scanCode &= 0x1ff; /* keep "extended-key" flag with code */ + +@@ -2232,7 +2232,7 @@ INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize) + return rc; + } + } +- ++#endif + /* Finally issue WARN for unknown keys */ + + LeaveCriticalSection( &kbd_section ); +diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c +index e5592184337..d1b1cd362c0 100644 +--- a/dlls/winex11.drv/x11drv_main.c ++++ b/dlls/winex11.drv/x11drv_main.c +@@ -624,10 +624,11 @@ static BOOL process_attach(void) + X11DRV_XComposite_Init(); + #endif + X11DRV_XInput2_Init(); +- ++/* + #ifdef HAVE_XKB + if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL ); + #endif ++*/ + X11DRV_InitKeyboard( gdi_display ); + if (use_xim) use_xim = X11DRV_InitXIM( input_style ); + +diff --git a/dlls/ws2_32/unixlib.c b/dlls/ws2_32/unixlib.c +index 4b9274bf867..d46ac996968 100644 +--- a/dlls/ws2_32/unixlib.c ++++ b/dlls/ws2_32/unixlib.c +@@ -90,6 +90,7 @@ + # include + # define HAS_IRDA + #endif ++#define HAVE_GETADDRINFO + + #include "ntstatus.h" + #define WIN32_NO_STATUS +diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c +index 659ca364544..3a503dccaf3 100644 +--- a/programs/winedbg/winedbg.c ++++ b/programs/winedbg/winedbg.c +@@ -621,6 +621,8 @@ static void restart_if_wow64(void) + + int main(int argc, char** argv) + { ++ return 0; ++ + int retv = 0; + HANDLE hFile = INVALID_HANDLE_VALUE; + enum dbg_start ds; +diff --git a/server/fd.c b/server/fd.c +index 1a0840f4113..3b47269aef7 100644 +--- a/server/fd.c ++++ b/server/fd.c +@@ -1001,6 +1001,7 @@ void main_loop(void) + + if (!active_users) break; /* last user removed by a timeout */ + ++ //printf("poll(%d, %d), active_users: %d\n", nb_users, timeout, active_users); + ret = poll( pollfd, nb_users, timeout ); + set_current_time(); + +diff --git a/server/signal.c b/server/signal.c +index 05dafe154f5..c620d7c2af3 100644 +--- a/server/signal.c ++++ b/server/signal.c +@@ -259,6 +259,7 @@ int watchdog_triggered(void) + + static int core_dump_disabled( void ) + { ++#if 0 + int r = 0; + #ifdef RLIMIT_CORE + struct rlimit lim; +@@ -266,6 +267,8 @@ static int core_dump_disabled( void ) + r = !getrlimit(RLIMIT_CORE, &lim) && (lim.rlim_cur == 0); + #endif + return r; ++#endif ++ return 0; + } + + void init_signals(void) +diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c +index e8457e46643..0626329837b 100644 +--- a/tools/winegcc/winegcc.c ++++ b/tools/winegcc/winegcc.c +@@ -1341,6 +1341,9 @@ static void build(struct options* opts) + { + strarray_add(&link_args, "-lm"); + strarray_add(&link_args, "-lc"); ++#ifdef __HAIKU__ ++ strarray_add(&link_args, "-lnetwork"); ++#endif + } + + if (libgcc) strarray_add(&link_args, libgcc); +-- +2.30.2 + + +From e63186126bd1bc120ae6f919f29dd5d68a9e17c9 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Tue, 25 Jan 2022 22:12:25 +0900 +Subject: ntdll: register PE modules for Haiku + +--- + dlls/ntdll/unix/virtual.c | 51 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 49 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index ca6bb6caceb..86778e158d3 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -22,14 +22,19 @@ + #pragma makedep unix + #endif + ++#include "config.h" ++ + #define cpu_info haiku_cpu_info + #if defined(__HAIKU__) + # include ++# include ++ ++extern image_id _kern_register_image(extended_image_info *info, size_t size); ++extern status_t _kern_unregister_image(image_id id); ++ + #endif + #undef cpu_info + +-#include "config.h" +- + #include + #include + #include +@@ -625,6 +630,47 @@ void release_builtin_module( void *module ) + } + + ++static void haiku_register_module( void *module, int fd, WCHAR *wpath ) ++{ ++ IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)module; ++ IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((char*)module + dos->e_lfanew); ++ ++ struct stat stat; ++ fstat(fd, &stat); ++ ++ extended_image_info info = { ++ .basic_info = { ++ .type = (true || (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) ? B_LIBRARY_IMAGE : B_APP_IMAGE, ++ .device = stat.st_dev, ++ .node = stat.st_ino, ++ .text = (uint8*)module + nt->OptionalHeader.BaseOfCode, ++ .data = (uint8*)module + nt->OptionalHeader.BaseOfCode + nt->OptionalHeader.SizeOfCode, ++ .text_size = nt->OptionalHeader.SizeOfCode, ++ .data_size = nt->OptionalHeader.SizeOfImage - nt->OptionalHeader.BaseOfCode, ++ }, ++ .text_delta = (int64)module + nt->OptionalHeader.BaseOfCode - (int64)nt->OptionalHeader.ImageBase ++ }; ++ ntdll_wcstoumbs(wpath, wcslen(wpath), info.basic_info.name, MAXPATHLEN, FALSE); ++ ++ if (true || strstr(info.basic_info.name, ".so") != NULL) ++ return; ++/* ++ static const char builtin_signature[32] = "Wine builtin DLL"; ++ if (memcmp( dos + 1, builtin_signature, sizeof(builtin_signature) ) == 0) ++ return; ++*/ ++ for (size_t i = 0; info.basic_info.name[i] != '\0'; i++) { ++ if (info.basic_info.name[i] == '\\') ++ info.basic_info.name[i] = '/'; ++ } ++ _kern_register_image(&info, sizeof(info)); ++} ++ ++static void haiku_unregister_module( void *module ) ++{ ++} ++ ++ + /*********************************************************************** + * get_builtin_so_handle + */ +@@ -2537,6 +2583,7 @@ static NTSTATUS virtual_map_image( HANDLE mapping, ACCESS_MASK access, void **ad + if (status >= 0) + { + if (is_builtin) add_builtin_module( view->base, NULL ); ++ haiku_register_module(view->base, unix_fd, filename); + *addr_ptr = view->base; + *size_ptr = size; + VIRTUAL_DEBUG_DUMP_VIEW( view ); +-- +2.30.2 + + +From 8300eac14bc52a462a1e03173590168801e6d8e7 Mon Sep 17 00:00:00 2001 +From: X512 +Date: Tue, 25 Jan 2022 22:13:57 +0900 +Subject: winehaiku.drv: update + +--- + dlls/winehaiku.drv/window.cpp | 38 +++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/dlls/winehaiku.drv/window.cpp b/dlls/winehaiku.drv/window.cpp +index 18dcba70c69..41331e31c24 100644 +--- a/dlls/winehaiku.drv/window.cpp ++++ b/dlls/winehaiku.drv/window.cpp +@@ -536,6 +536,16 @@ WineWindow* HaikuThisWindow(HWND hwnd, bool create) + return window; + } + ++static void HaikuRemoveWindow(HWND hwnd) ++{ ++ BAutolock lock(be_app); ++ auto it = sWindows->find(hwnd); ++ if (it == sWindows->end()) { ++ ERR("hwnd %p not present in host window list\n", hwnd); ++ } ++ sWindows->erase(it); ++} ++ + + //#pragma mark - window_surface + +@@ -760,9 +770,16 @@ static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rec + { + DWORD style, ex_style; + ++ return hwnd == GetAncestor(hwnd, GA_ROOT); ++ + /* child windows are not managed */ + style = GetWindowLongW( hwnd, GWL_STYLE ); +- if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) return FALSE; ++ if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) { ++ HWND hwndParent = GetParent(hwnd); ++ if (hwndParent == GetDesktopWindow()) ++ return TRUE; ++ return FALSE; ++ } + return TRUE; + + /* activated windows are managed */ +@@ -899,6 +916,7 @@ static void GetHaikuWindowFlags( + } + else if (ex_style & WS_EX_DLGMODALFRAME) {if (look == B_NO_BORDER_WINDOW_LOOK) look = B_MODAL_WINDOW_LOOK;} + else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) {if (look == B_NO_BORDER_WINDOW_LOOK) look = B_MODAL_WINDOW_LOOK;} ++ else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_BORDER) {if (look == B_NO_BORDER_WINDOW_LOOK) look = B_BORDERED_WINDOW_LOOK;} + } + + +@@ -951,6 +969,7 @@ void CDECL HAIKUDRV_DestroyWindow( HWND hwnd ) + wnd->fInDestroy = true; + BMessenger(wnd).SendMessage(B_QUIT_REQUESTED); + wnd->Unlock(); ++ HaikuRemoveWindow(hwnd); + } + + +@@ -1043,7 +1062,7 @@ BOOL CDECL HAIKUDRV_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update ) + void CDECL HAIKUDRV_SetCapture( HWND hwnd, UINT flags ) + { + FIXME("(%ld, %x): stub\n", (long)hwnd, flags); +- return; ++ hwnd = GetAncestor(hwnd, GA_ROOT); + if (hwnd == sCaptureWnd) return; + WineWindow* prevWnd = HaikuThisWindow(sCaptureWnd, false); + if (prevWnd != NULL) { +@@ -1051,7 +1070,8 @@ void CDECL HAIKUDRV_SetCapture( HWND hwnd, UINT flags ) + prevWnd->View()->SetEventMask(0); + prevWnd->Unlock(); + } +- WineWindow* nextWnd = HaikuThisWindow(hwnd, false); ++ sCaptureWnd = hwnd; ++ WineWindow* nextWnd = HaikuThisWindow(sCaptureWnd, false); + if (nextWnd != NULL) { + nextWnd->Lock(); + nextWnd->View()->SetEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS); +@@ -1077,13 +1097,15 @@ BOOL CDECL HAIKUDRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_fl + struct window_surface **surface ) + { + //FIXME("(%ld): stub\n", (long)hwnd); +- ERR("(%ld)\n", (long)hwnd); ++ char className[256]; ++ GetClassNameA(hwnd, className, 256); ++ //ERR("(%ld), class: \"%s\"\n", (long)hwnd, className); + + if (hwnd == GetDesktopWindow()) return TRUE; + if (!is_window_managed( hwnd, swp_flags, window_rect )) return TRUE; + +- ERR("window_rect: (%d, %d, %d, %d)\n", window_rect->left, window_rect->top, window_rect->right, window_rect->bottom); +- ERR("client_rect: (%d, %d, %d, %d)\n", client_rect->left, client_rect->top, client_rect->right, client_rect->bottom); ++ //ERR("window_rect: (%d, %d, %d, %d)\n", window_rect->left, window_rect->top, window_rect->right, window_rect->bottom); ++ //ERR("client_rect: (%d, %d, %d, %d)\n", client_rect->left, client_rect->top, client_rect->right, client_rect->bottom); + + DWORD style = GetWindowLongW(hwnd, GWL_STYLE); + DWORD exStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); +@@ -1133,11 +1155,11 @@ void CDECL HAIKUDRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_fla + const RECT *visible_rect, const RECT *valid_rects, + struct window_surface *surface ) + { +- ERR("(%ld)\n", (long)hwnd); ++ //ERR("(%ld)\n", (long)hwnd); + WineWindow *window = HaikuThisWindow(hwnd, false); + if (window == NULL) return; + +- ERR("(%p, swp_flags: %x)\n", hwnd, swp_flags); ++ //ERR("(%p, swp_flags: %x)\n", hwnd, swp_flags); + + DWORD style = GetWindowLongW(hwnd, GWL_STYLE); + DWORD exStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); +-- +2.30.2 + diff --git a/app-emulation/wine/wine-6.23.recipe b/app-emulation/wine/wine-6.23.recipe new file mode 100644 index 000000000..0c8948cd7 --- /dev/null +++ b/app-emulation/wine/wine-6.23.recipe @@ -0,0 +1,89 @@ +SUMMARY="Program which allows running Microsoft Windows programs" +DESCRIPTION="Wine is a program which allows running Microsoft Windows programs \ +(including DOS, Windows 3.x, Win32, and Win64 executables) on Unix. \ +It consists of a program loader which loads and executes a Microsoft \ +Windows binary, and a library (called Winelib) that implements Windows \ +API calls using their Unix, X11 or Mac equivalents. The library may also \ +be used for porting Windows code into native Unix executables." +HOMEPAGE="https://www.winehq.org/" +COPYRIGHT="1993-2021 the Wine project authors" +LICENSE="GNU LGPL v2.1" +REVISION="1" +SOURCE_URI="https://github.com/wine-mirror/wine/archive/refs/tags/wine-${portVersion}.tar.gz" +CHECKSUM_SHA256="a377546970b780d1d184d7a9dc45cc3c4373541de2861c8fb354008ff965f79a" +SOURCE_DIR="wine-wine-${portVersion}" +PATCHES="wine-$portVersion.patchset" + +ARCHITECTURES="all !x86_gcc2" +SECONDARY_ARCHITECTURES="!x86" + +PROVIDES=" + wine$secondaryArchSuffix = $portVersion + cmd:wine64$secondaryArchSuffix = $portVersion + cmd:function_grep.pl + cmd:msidb + cmd:msiexec + cmd:notepad + cmd:regedit + cmd:regsvr32 + cmd:widl + cmd:wineboot + cmd:winebuild + cmd:winecfg + cmd:wineconsole + cmd:winecpp + cmd:winedbg + cmd:winedump + cmd:winefile + cmd:wineg++ + cmd:winegcc + cmd:winemaker + cmd:winemine + cmd:winepath + cmd:wineserver + cmd:wmc + cmd:wrc + " +REQUIRES=" + haiku$secondaryArchSuffix + lib:libfreetype$secondaryArchSuffix + lib:libvulkan$secondaryArchSuffix + lib:libusb$secondaryArchSuffix + " + +BUILD_REQUIRES=" + devel:libfreetype$secondaryArchSuffix + devel:libvulkan$secondaryArchSuffix + devel:libusb$secondaryArchSuffix + " +BUILD_PREREQUIRES=" + haiku${secondaryArchSuffix}_devel + cmd:autoconf + cmd:automake + cmd:cp + cmd:gcc$secondaryArchSuffix + cmd:ld$secondaryArchSuffix + cmd:make + cmd:sed + cmd:flex + cmd:bison + cmd:pkg_config$secondaryArchSuffix + cmd:mkdepend + cmd:gettext + llvm12 + llvm12_clang + llvm12_lld + " + +BUILD() +{ + autoreconf -i + LDFLAGS=-lnetwork runConfigure ./configure --enable-win64 --without-x --without-xshm + + make $jobArgs +} + +INSTALL() +{ + make install +}