From e910c7d9bf8e981bb1b7458c4793c5aedee98850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 8 Jan 2022 22:38:55 +0100 Subject: [PATCH 01/21] configure: Allow passing extra Objective C compiler flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can pass C/CPP/LD flags via CFLAGS/CXXFLAGS/LDFLAGS environment variables, or via configure --extra-cflags / --extra-cxxflags / --extra-ldflags options. Provide similar behavior for Objective C: use existing flags from $OBJCFLAGS, or passed via --extra-objcflags. Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- configure | 8 ++++++++ meson.build | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/configure b/configure index 886000346a..2bf40d9eeb 100755 --- a/configure +++ b/configure @@ -285,6 +285,7 @@ done EXTRA_CFLAGS="" EXTRA_CXXFLAGS="" +EXTRA_OBJCFLAGS="" EXTRA_LDFLAGS="" xen_ctrl_version="$default_feature" @@ -366,9 +367,12 @@ for opt do --extra-cflags=*) EXTRA_CFLAGS="$EXTRA_CFLAGS $optarg" EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS $optarg" + EXTRA_OBJCFLAGS="$EXTRA_OBJCFLAGS $optarg" ;; --extra-cxxflags=*) EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS $optarg" ;; + --extra-objcflags=*) EXTRA_OBJCFLAGS="$EXTRA_OBJCFLAGS $optarg" + ;; --extra-ldflags=*) EXTRA_LDFLAGS="$EXTRA_LDFLAGS $optarg" ;; --enable-debug-info) debug_info="yes" @@ -748,6 +752,8 @@ for opt do ;; --extra-cxxflags=*) ;; + --extra-objcflags=*) + ;; --extra-ldflags=*) ;; --enable-debug-info) @@ -1172,6 +1178,7 @@ Advanced options (experts only): --objcc=OBJCC use Objective-C compiler OBJCC [$objcc] --extra-cflags=CFLAGS append extra C compiler flags CFLAGS --extra-cxxflags=CXXFLAGS append extra C++ compiler flags CXXFLAGS + --extra-objcflags=OBJCFLAGS append extra Objective C compiler flags OBJCFLAGS --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS --cross-cc-ARCH=CC use compiler when building ARCH guest test cases --cross-cc-cflags-ARCH= use compiler flags when building ARCH guest tests @@ -3137,6 +3144,7 @@ if test "$skip_meson" = no; then echo "[built-in options]" >> $cross echo "c_args = [$(meson_quote $CFLAGS $EXTRA_CFLAGS)]" >> $cross echo "cpp_args = [$(meson_quote $CXXFLAGS $EXTRA_CXXFLAGS)]" >> $cross + test -n "$objcc" && echo "objc_args = [$(meson_quote $OBJCFLAGS $EXTRA_OBJCFLAGS)]" >> $cross echo "c_link_args = [$(meson_quote $CFLAGS $LDFLAGS $EXTRA_CFLAGS $EXTRA_LDFLAGS)]" >> $cross echo "cpp_link_args = [$(meson_quote $CXXFLAGS $LDFLAGS $EXTRA_CXXFLAGS $EXTRA_LDFLAGS)]" >> $cross echo "[binaries]" >> $cross diff --git a/meson.build b/meson.build index 2d6601467f..351f9f4360 100644 --- a/meson.build +++ b/meson.build @@ -3467,6 +3467,11 @@ if link_language == 'cpp' + ['-O' + get_option('optimization')] + (get_option('debug') ? ['-g'] : []))} endif +if targetos == 'darwin' + summary_info += {'OBJCFLAGS': ' '.join(get_option('objc_args') + + ['-O' + get_option('optimization')] + + (get_option('debug') ? ['-g'] : []))} +endif link_args = get_option(link_language + '_link_args') if link_args.length() > 0 summary_info += {'LDFLAGS': ' '.join(link_args)} From 004900acbcde82d52d80404dea7f43ce5f8b78fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Feb 2022 15:14:39 +0100 Subject: [PATCH 02/21] tests/fp/berkeley-testfloat-3: Ignore ignored #pragma directives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we already use -Wno-unknown-pragmas, we can also use -Wno-ignored-pragmas. This silences hundred of warnings using clang 13 on macOS Monterey: [409/771] Compiling C object tests/fp/libtestfloat.a.p/berkeley-testfloat-3_source_test_az_f128_rx.c.o ../tests/fp/berkeley-testfloat-3/source/test_az_f128_rx.c:49:14: warning: '#pragma FENV_ACCESS' is not supported on this target - ignored [-Wignored-pragmas] #pragma STDC FENV_ACCESS ON ^ 1 warning generated. Having: $ cc -v Apple clang version 13.0.0 (clang-1300.0.29.30) Reported-by: Roman Bolshakov Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Acked-by: Alex Bennée Signed-off-by: Philippe Mathieu-Daudé --- tests/fp/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/fp/meson.build b/tests/fp/meson.build index 59776a00a7..8bd0979f67 100644 --- a/tests/fp/meson.build +++ b/tests/fp/meson.build @@ -37,6 +37,11 @@ tfcflags = [ '-Wno-error', ] +if cc.get_id() == 'clang' + # Clang does not support '#pragma STDC FENV_ACCESS' + tfcflags += [ '-Wno-ignored-pragmas' ] +endif + tfgencases = [ tfdir / 'genCases_ui32.c', tfdir / 'genCases_ui64.c', From 704afe34d8c4dbee3e88cfaa25c8561364169695 Mon Sep 17 00:00:00 2001 From: Cameron Esfahani Date: Thu, 28 Oct 2021 18:33:15 -0700 Subject: [PATCH 03/21] hvf: Use standard CR0 and CR4 register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to have our own definitions of these registers. Signed-off-by: Cameron Esfahani Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- target/i386/hvf/vmx.h | 17 +++++++++-------- target/i386/hvf/x86.c | 6 +++--- target/i386/hvf/x86.h | 34 ---------------------------------- target/i386/hvf/x86_mmu.c | 2 +- target/i386/hvf/x86_task.c | 3 ++- 5 files changed, 15 insertions(+), 47 deletions(-) diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index 6df87116f6..29b7deed3c 100644 --- a/target/i386/hvf/vmx.h +++ b/target/i386/hvf/vmx.h @@ -124,10 +124,11 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER); uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0); uint64_t changed_cr0 = old_cr0 ^ cr0; - uint64_t mask = CR0_PG | CR0_CD | CR0_NW | CR0_NE | CR0_ET; + uint64_t mask = CR0_PG_MASK | CR0_CD_MASK | CR0_NW_MASK | + CR0_NE_MASK | CR0_ET_MASK; uint64_t entry_ctls; - if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) && + if ((cr0 & CR0_PG_MASK) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE_MASK) && !(efer & MSR_EFER_LME)) { address_space_read(&address_space_memory, rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f, @@ -142,8 +143,8 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) wvmcs(vcpu, VMCS_CR0_SHADOW, cr0); if (efer & MSR_EFER_LME) { - if (changed_cr0 & CR0_PG) { - if (cr0 & CR0_PG) { + if (changed_cr0 & CR0_PG_MASK) { + if (cr0 & CR0_PG_MASK) { enter_long_mode(vcpu, cr0, efer); } else { exit_long_mode(vcpu, cr0, efer); @@ -155,8 +156,8 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) } /* Filter new CR0 after we are finished examining it above. */ - cr0 = (cr0 & ~(mask & ~CR0_PG)); - wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET); + cr0 = (cr0 & ~(mask & ~CR0_PG_MASK)); + wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE_MASK | CR0_ET_MASK); hv_vcpu_invalidate_tlb(vcpu); hv_vcpu_flush(vcpu); @@ -164,11 +165,11 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) { - uint64_t guest_cr4 = cr4 | CR4_VMXE; + uint64_t guest_cr4 = cr4 | CR4_VMXE_MASK; wvmcs(vcpu, VMCS_GUEST_CR4, guest_cr4); wvmcs(vcpu, VMCS_CR4_SHADOW, cr4); - wvmcs(vcpu, VMCS_CR4_MASK, CR4_VMXE); + wvmcs(vcpu, VMCS_CR4_MASK, CR4_VMXE_MASK); hv_vcpu_invalidate_tlb(vcpu); hv_vcpu_flush(vcpu); diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index 2898bb70a8..91a3fe002c 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -119,7 +119,7 @@ bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc, bool x86_is_protected(struct CPUState *cpu) { uint64_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0); - return cr0 & CR0_PE; + return cr0 & CR0_PE_MASK; } bool x86_is_real(struct CPUState *cpu) @@ -150,13 +150,13 @@ bool x86_is_long64_mode(struct CPUState *cpu) bool x86_is_paging_mode(struct CPUState *cpu) { uint64_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0); - return cr0 & CR0_PG; + return cr0 & CR0_PG_MASK; } bool x86_is_pae_enabled(struct CPUState *cpu) { uint64_t cr4 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR4); - return cr4 & CR4_PAE; + return cr4 & CR4_PAE_MASK; } target_ulong linear_addr(struct CPUState *cpu, target_ulong addr, X86Seg seg) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index 782664c2ea..947b98da41 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -42,40 +42,6 @@ typedef struct x86_register { }; } __attribute__ ((__packed__)) x86_register; -typedef enum x86_reg_cr0 { - CR0_PE = (1L << 0), - CR0_MP = (1L << 1), - CR0_EM = (1L << 2), - CR0_TS = (1L << 3), - CR0_ET = (1L << 4), - CR0_NE = (1L << 5), - CR0_WP = (1L << 16), - CR0_AM = (1L << 18), - CR0_NW = (1L << 29), - CR0_CD = (1L << 30), - CR0_PG = (1L << 31), -} x86_reg_cr0; - -typedef enum x86_reg_cr4 { - CR4_VME = (1L << 0), - CR4_PVI = (1L << 1), - CR4_TSD = (1L << 2), - CR4_DE = (1L << 3), - CR4_PSE = (1L << 4), - CR4_PAE = (1L << 5), - CR4_MSE = (1L << 6), - CR4_PGE = (1L << 7), - CR4_PCE = (1L << 8), - CR4_OSFXSR = (1L << 9), - CR4_OSXMMEXCPT = (1L << 10), - CR4_VMXE = (1L << 13), - CR4_SMXE = (1L << 14), - CR4_FSGSBASE = (1L << 16), - CR4_PCIDE = (1L << 17), - CR4_OSXSAVE = (1L << 18), - CR4_SMEP = (1L << 20), -} x86_reg_cr4; - /* 16 bit Task State Segment */ typedef struct x86_tss_segment16 { uint16_t link; diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/hvf/x86_mmu.c index e9ed0f5aa1..df0b91cd42 100644 --- a/target/i386/hvf/x86_mmu.c +++ b/target/i386/hvf/x86_mmu.c @@ -129,7 +129,7 @@ static bool test_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, uint32_t cr0 = rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0); /* check protection */ - if (cr0 & CR0_WP) { + if (cr0 & CR0_WP_MASK) { if (pt->write_access && !pte_write_access(pte)) { return false; } diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 422156128b..e1301599e9 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -174,7 +174,8 @@ void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int rea //ret = task_switch_16(cpu, tss_sel, old_tss_sel, old_tss_base, &next_tss_desc); VM_PANIC("task_switch_16"); - macvm_set_cr0(cpu->hvf->fd, rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0) | CR0_TS); + macvm_set_cr0(cpu->hvf->fd, rvmcs(cpu->hvf->fd, VMCS_GUEST_CR0) | + CR0_TS_MASK); x86_segment_descriptor_to_vmx(cpu, tss_sel, &next_tss_desc, &vmx_seg); vmx_write_segment_descriptor(cpu, &vmx_seg, R_TR); From 40eab4d95939c47f5bf6e664868c172090856244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 8 Jan 2022 16:58:10 +0100 Subject: [PATCH 04/21] hvf: Make hvf_get_segments() / hvf_put_segments() local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both hvf_get_segments/hvf_put_segments() functions are only used within x86hvf.c: do not declare them as public API. Reviewed-by: Roman Bolshakov Tested-by: Roman Bolshakov Signed-off-by: Philippe Mathieu-Daudé --- target/i386/hvf/x86hvf.c | 4 ++-- target/i386/hvf/x86hvf.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 05ec1bddc4..907f09f1b4 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -83,7 +83,7 @@ void hvf_put_xsave(CPUState *cpu_state) } } -void hvf_put_segments(CPUState *cpu_state) +static void hvf_put_segments(CPUState *cpu_state) { CPUX86State *env = &X86_CPU(cpu_state)->env; struct vmx_segment seg; @@ -166,7 +166,7 @@ void hvf_get_xsave(CPUState *cpu_state) x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave, xsave_len); } -void hvf_get_segments(CPUState *cpu_state) +static void hvf_get_segments(CPUState *cpu_state) { CPUX86State *env = &X86_CPU(cpu_state)->env; diff --git a/target/i386/hvf/x86hvf.h b/target/i386/hvf/x86hvf.h index 99ed8d608d..db6003d6bd 100644 --- a/target/i386/hvf/x86hvf.h +++ b/target/i386/hvf/x86hvf.h @@ -26,11 +26,9 @@ void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr); void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg); void hvf_put_xsave(CPUState *cpu_state); -void hvf_put_segments(CPUState *cpu_state); void hvf_put_msrs(CPUState *cpu_state); void hvf_get_xsave(CPUState *cpu_state); void hvf_get_msrs(CPUState *cpu_state); void vmx_clear_int_window_exiting(CPUState *cpu); -void hvf_get_segments(CPUState *cpu_state); void vmx_update_tpr(CPUState *cpu); #endif From 2e84d8521f596689d96e07ac377d2af1479774ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 8 Jan 2022 16:59:49 +0100 Subject: [PATCH 05/21] hvf: Remove deprecated hv_vcpu_flush() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building on macOS 11 [*], we get: In file included from ../target/i386/hvf/hvf.c:59: ../target/i386/hvf/vmx.h:174:5: error: 'hv_vcpu_flush' is deprecated: first deprecated in macOS 11.0 - This API has no effect and always returns HV_UNSUPPORTED [-Werror,-Wdeprecated-declarations] hv_vcpu_flush(vcpu); ^ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Hypervisor.framework/Headers/hv.h:364:20: note: 'hv_vcpu_flush' has been explicitly marked deprecated here extern hv_return_t hv_vcpu_flush(hv_vcpuid_t vcpu) ^ Since this call "has no effect", simply remove it ¯\_(ツ)_/¯ Not very useful deprecation doc: https://developer.apple.com/documentation/hypervisor/1441386-hv_vcpu_flush [*] Also 10.15 (Catalina): https://lore.kernel.org/qemu-devel/Yd3DmSqZ1SiJwd7P@roolebo.dev/ Reviewed-by: Roman Bolshakov Tested-by: Roman Bolshakov Signed-off-by: Philippe Mathieu-Daudé --- target/i386/hvf/vmx.h | 2 -- target/i386/hvf/x86_task.c | 1 - target/i386/hvf/x86hvf.c | 2 -- 3 files changed, 5 deletions(-) diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index 29b7deed3c..573ddc33c0 100644 --- a/target/i386/hvf/vmx.h +++ b/target/i386/hvf/vmx.h @@ -160,7 +160,6 @@ static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE_MASK | CR0_ET_MASK); hv_vcpu_invalidate_tlb(vcpu); - hv_vcpu_flush(vcpu); } static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) @@ -172,7 +171,6 @@ static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) wvmcs(vcpu, VMCS_CR4_MASK, CR4_VMXE_MASK); hv_vcpu_invalidate_tlb(vcpu); - hv_vcpu_flush(vcpu); } static inline void macvm_set_rip(CPUState *cpu, uint64_t rip) diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index e1301599e9..d24daf6a41 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -182,5 +182,4 @@ void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int rea store_regs(cpu); hv_vcpu_invalidate_tlb(cpu->hvf->fd); - hv_vcpu_flush(cpu->hvf->fd); } diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 907f09f1b4..bec9fc5814 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -125,8 +125,6 @@ static void hvf_put_segments(CPUState *cpu_state) hvf_set_segment(cpu_state, &seg, &env->ldt, false); vmx_write_segment_descriptor(cpu_state, &seg, R_LDTR); - - hv_vcpu_flush(cpu_state->hvf->fd); } void hvf_put_msrs(CPUState *cpu_state) From aa44d3f6b8d2f08f09034f287efec8890633cc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 6 Jan 2022 00:46:01 +0100 Subject: [PATCH 06/21] block/file-posix: Remove a deprecation warning on macOS 12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building on macOS 12 we get: block/file-posix.c:3335:18: warning: 'IOMasterPort' is deprecated: first deprecated in macOS 12.0 [-Wdeprecated-declarations] kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); ^~~~~~~~~~~~ IOMainPort Replace by IOMainPort, redefining it to IOMasterPort if not available. Suggested-by: Akihiko Odaki Reviewed-by: Christian Schoenebeck Reviewed by: Cameron Esfahani Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- block/file-posix.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index c000a61db2..39a3d6dbe6 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3320,17 +3320,23 @@ BlockDriver bdrv_file = { #if defined(__APPLE__) && defined(__MACH__) static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize, int flags); + +#if !defined(MAC_OS_VERSION_12_0) \ + || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0) +#define IOMainPort IOMasterPort +#endif + static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator) { kern_return_t kernResult = KERN_FAILURE; - mach_port_t masterPort; + mach_port_t mainPort; CFMutableDictionaryRef classesToMatch; const char *matching_array[] = {kIODVDMediaClass, kIOCDMediaClass}; char *mediaType = NULL; - kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); + kernResult = IOMainPort(MACH_PORT_NULL, &mainPort); if ( KERN_SUCCESS != kernResult ) { - printf( "IOMasterPort returned %d\n", kernResult ); + printf("IOMainPort returned %d\n", kernResult); } int index; @@ -3343,7 +3349,7 @@ static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator) } CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue); - kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, + kernResult = IOServiceGetMatchingServices(mainPort, classesToMatch, mediaIterator); if (kernResult != KERN_SUCCESS) { error_report("Note: IOServiceGetMatchingServices returned %d", From 9f56bd6dab1a73362aefb7fe7bb8e364410d9d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 9 Jan 2022 14:30:03 +0100 Subject: [PATCH 07/21] audio/coreaudio: Remove a deprecation warning on macOS 12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building on macOS 12 we get: audio/coreaudio.c:50:5: error: 'kAudioObjectPropertyElementMaster' is deprecated: first deprecated in macOS 12.0 [-Werror,-Wdeprecated-declarations] kAudioObjectPropertyElementMaster ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kAudioObjectPropertyElementMain /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreAudio.framework/Headers/AudioHardwareBase.h:208:5: note: 'kAudioObjectPropertyElementMaster' has been explicitly marked deprecated here kAudioObjectPropertyElementMaster API_DEPRECATED_WITH_REPLACEMENT("kAudioObjectPropertyElementMain", macos(10.0, 12.0), ios(2.0, 15.0), watchos(1.0, 8.0), tvos(9.0, 15.0)) = kAudioObjectPropertyElementMain ^ Replace by kAudioObjectPropertyElementMain, redefining it to kAudioObjectPropertyElementMaster if not available. Suggested-by: Akihiko Odaki Suggested-by: Christian Schoenebeck Suggested-by: Roman Bolshakov Reviewed-by: Christian Schoenebeck Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- audio/coreaudio.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 0f19d0ce01..23d7593eb9 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -44,10 +44,15 @@ typedef struct coreaudioVoiceOut { bool enabled; } coreaudioVoiceOut; +#if !defined(MAC_OS_VERSION_12_0) \ + || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0) +#define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster +#endif + static const AudioObjectPropertyAddress voice_addr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; static OSStatus coreaudio_get_voice(AudioDeviceID *id) @@ -69,7 +74,7 @@ static OSStatus coreaudio_get_framesizerange(AudioDeviceID id, AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; return AudioObjectGetPropertyData(id, @@ -86,7 +91,7 @@ static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize) AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSize, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; return AudioObjectGetPropertyData(id, @@ -103,7 +108,7 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize) AudioObjectPropertyAddress addr = { kAudioDevicePropertyBufferFrameSize, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; return AudioObjectSetPropertyData(id, @@ -121,7 +126,7 @@ static OSStatus coreaudio_set_streamformat(AudioDeviceID id, AudioObjectPropertyAddress addr = { kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; return AudioObjectSetPropertyData(id, @@ -138,7 +143,7 @@ static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result) AudioObjectPropertyAddress addr = { kAudioDevicePropertyDeviceIsRunning, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster + kAudioObjectPropertyElementMain }; return AudioObjectGetPropertyData(id, From c9c847481e70f2f5065605b6d21f7f8d72e54607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Feb 2022 16:25:09 +0100 Subject: [PATCH 08/21] audio/dbus: Fix building with modules on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When configuring QEMU with --enable-modules we get on macOS: --- stderr --- Dependency ui-dbus cannot be satisfied ui-dbus depends on pixman and opengl, so add these dependencies to audio-dbus. Fixes: 739362d420 ("audio: add "dbus" audio backend") Reviewed-by: Li Zhang Signed-off-by: Philippe Mathieu-Daudé --- audio/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/meson.build b/audio/meson.build index 0ac3791d0b..d9b295514f 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -28,7 +28,7 @@ endforeach if dbus_display module_ss = ss.source_set() - module_ss.add(when: gio, if_true: files('dbusaudio.c')) + module_ss.add(when: [gio, pixman, opengl, 'CONFIG_GIO'], if_true: files('dbusaudio.c')) audio_modules += {'dbus': module_ss} endif From 8e30d39bade3010387177ca23dbc2244352ed4a3 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 6 Mar 2022 15:32:02 +0900 Subject: [PATCH 09/21] audio: Log context for audio bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this change audio_bug aborts when the bug condition is met, which discards following useful logs. Call abort after such logs. Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220306063202.27331-1-akihiko.odaki@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- audio/audio.c | 25 ++++++++++++------------- audio/audio_template.h | 27 ++++++++++++--------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index a88572e713..6bc313d9f5 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -117,7 +117,6 @@ int audio_bug (const char *funcname, int cond) AUD_log (NULL, "I am sorry\n"); } AUD_log (NULL, "Context:\n"); - abort(); } return cond; @@ -138,7 +137,7 @@ static inline int audio_bits_to_index (int bits) default: audio_bug ("bits_to_index", 1); AUD_log (NULL, "invalid bits %d\n", bits); - return 0; + abort(); } } @@ -156,7 +155,7 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size) AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n", funcname); AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len); - return NULL; + abort(); } return g_malloc0 (len); @@ -543,7 +542,7 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug(__func__, live > hw->conv_buf->size)) { dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); - return 0; + abort(); } return live; } @@ -581,7 +580,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) } if (audio_bug(__func__, live > hw->conv_buf->size)) { dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); - return 0; + abort(); } rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size); @@ -656,7 +655,7 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) if (audio_bug(__func__, live > hw->mix_buf->size)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); - return 0; + abort(); } return live; } @@ -706,7 +705,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) live = sw->total_hw_samples_mixed; if (audio_bug(__func__, live > hwsamples)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples); - return 0; + abort(); } if (live == hwsamples) { @@ -998,7 +997,7 @@ static size_t audio_get_avail (SWVoiceIn *sw) if (audio_bug(__func__, live > sw->hw->conv_buf->size)) { dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live, sw->hw->conv_buf->size); - return 0; + abort(); } ldebug ( @@ -1028,7 +1027,7 @@ static size_t audio_get_free(SWVoiceOut *sw) if (audio_bug(__func__, live > sw->hw->mix_buf->size)) { dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live, sw->hw->mix_buf->size); - return 0; + abort(); } dead = sw->hw->mix_buf->size - live; @@ -1170,7 +1169,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, live > hw->mix_buf->size)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); - continue; + abort(); } if (hw->pending_disable && !nb_live) { @@ -1203,7 +1202,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) { dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n", hw->mix_buf->pos, hw->mix_buf->size, played); - hw->mix_buf->pos = 0; + abort(); } #ifdef DEBUG_OUT @@ -1223,7 +1222,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) { dolog("played=%zu sw->total_hw_samples_mixed=%zu\n", played, sw->total_hw_samples_mixed); - played = sw->total_hw_samples_mixed; + abort(); } sw->total_hw_samples_mixed -= played; @@ -1346,7 +1345,7 @@ static void audio_run_capture (AudioState *s) if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)) { dolog("captured=%zu sw->total_hw_samples_mixed=%zu\n", captured, sw->total_hw_samples_mixed); - captured = sw->total_hw_samples_mixed; + abort(); } sw->total_hw_samples_mixed -= captured; diff --git a/audio/audio_template.h b/audio/audio_template.h index d2d348638b..7192b19e73 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -59,12 +59,13 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, if (audio_bug(__func__, !voice_size && max_voices)) { dolog ("drv=`%s' voice_size=0 max_voices=%d\n", drv->name, max_voices); - glue (s->nb_hw_voices_, TYPE) = 0; + abort(); } if (audio_bug(__func__, voice_size && !max_voices)) { dolog ("drv=`%s' voice_size=%d max_voices=0\n", drv->name, voice_size); + abort(); } } @@ -81,6 +82,7 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) size_t samples = hw->samples; if (audio_bug(__func__, samples == 0)) { dolog("Attempted to allocate empty buffer\n"); + abort(); } HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples); @@ -252,12 +254,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, if (audio_bug(__func__, !drv)) { dolog ("No host audio driver\n"); - return NULL; + abort(); } if (audio_bug(__func__, !drv->pcm_ops)) { dolog ("Host audio driver without pcm_ops\n"); - return NULL; + abort(); } hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE)); @@ -275,12 +277,13 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, QLIST_INIT (&hw->cap_head); #endif if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) { - goto err0; + g_free(hw); + return NULL; } if (audio_bug(__func__, hw->samples <= 0)) { dolog("hw->samples=%zd\n", hw->samples); - goto err1; + abort(); } if (hw->info.is_float) { @@ -309,12 +312,6 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, audio_attach_capture (hw); #endif return hw; - - err1: - glue (hw->pcm_ops->fini_, TYPE) (hw); - err0: - g_free (hw); - return NULL; } AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) @@ -435,7 +432,7 @@ void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) if (sw) { if (audio_bug(__func__, !card)) { dolog ("card=%p\n", card); - return; + abort(); } glue (audio_close_, TYPE) (sw); @@ -457,7 +454,7 @@ SW *glue (AUD_open_, TYPE) ( if (audio_bug(__func__, !card || !name || !callback_fn || !as)) { dolog ("card=%p name=%p callback_fn=%p as=%p\n", card, name, callback_fn, as); - goto fail; + abort(); } s = card->state; @@ -468,12 +465,12 @@ SW *glue (AUD_open_, TYPE) ( if (audio_bug(__func__, audio_validate_settings(as))) { audio_print_settings (as); - goto fail; + abort(); } if (audio_bug(__func__, !s->drv)) { dolog ("Can not open `%s' (no host audio driver)\n", name); - goto fail; + abort(); } if (sw && audio_pcm_info_eq (&sw->info, as)) { From 44ccb2dbe9047586e3fb94bb2ece222e112e5eaf Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 6 Mar 2022 21:34:10 +0900 Subject: [PATCH 10/21] coreaudio: Always return 0 in handle_voice_change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit handle_voice_change() is a CoreAudio callback function as of CoreAudio type AudioObjectPropertyListenerProc, and for the latter MacOSX.sdk/System/ Library/Frameworks/CoreAudio.framework/Headers/AudioHardware.h says "The return value is currently unused and should always be 0.". Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220306123410.61063-1-akihiko.odaki@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- audio/coreaudio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 23d7593eb9..3186b68474 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -545,7 +545,6 @@ static OSStatus handle_voice_change( const AudioObjectPropertyAddress *in_addresses, void *in_client_data) { - OSStatus status; coreaudioVoiceOut *core = in_client_data; qemu_mutex_lock_iothread(); @@ -554,13 +553,12 @@ static OSStatus handle_voice_change( fini_out_device(core); } - status = init_out_device(core); - if (!status) { + if (!init_out_device(core)) { update_device_playback_state(core); } qemu_mutex_unlock_iothread(); - return status; + return 0; } static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, From 8b46d7e2dc8ec4b3515e43bc28ee77d9afab8b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 11:05:44 +0100 Subject: [PATCH 11/21] audio: Rename coreaudio extension to use Objective-C compiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coreaudio library includes Objective-C declarations (using the caret '^' symbol to declare block references [*]). When building with a C compiler we get: [175/839] Compiling C object libcommon.fa.p/audio_coreaudio.c.o In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h:18, from ../../audio/coreaudio.c:26: /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/System/Library/Frameworks/CoreAudio.framework/Headers/AudioHardware.h:162:2: error: expected identifier or '(' before '^' token 162 | (^AudioObjectPropertyListenerBlock)( UInt32 inNumberAddresses, | ^ FAILED: libcommon.fa.p/audio_coreaudio.c.o Rename the file to use the Objective-C default extension (.m) so meson calls the correct compiler. [*] https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html Reviewed-by: Christian Schoenebeck Signed-off-by: Philippe Mathieu-Daudé --- audio/{coreaudio.c => coreaudio.m} | 0 audio/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename audio/{coreaudio.c => coreaudio.m} (100%) diff --git a/audio/coreaudio.c b/audio/coreaudio.m similarity index 100% rename from audio/coreaudio.c rename to audio/coreaudio.m diff --git a/audio/meson.build b/audio/meson.build index d9b295514f..94dab16891 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -7,7 +7,7 @@ softmmu_ss.add(files( 'wavcapture.c', )) -softmmu_ss.add(when: coreaudio, if_true: files('coreaudio.c')) +softmmu_ss.add(when: coreaudio, if_true: files('coreaudio.m')) softmmu_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c')) audio_modules = {} From 98f5ebfd21b144fb70b02df3e419dec0ee2a52a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 12:34:58 +0100 Subject: [PATCH 12/21] osdep: Avoid using Clang-specific __builtin_available() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the Clang specific __builtin_available() to allow building with GCC, otherwise we get: include/qemu/osdep.h: In function 'qemu_thread_jit_write': include/qemu/osdep.h:787:9: warning: implicit declaration of function '__builtin_available'; did you mean '__builtin_scalbl'? [-Wimplicit-function-declaration] 787 | if (__builtin_available(macOS 11.0, *)) { | ^~~~~~~~~~~~~~~~~~~ | __builtin_scalbl include/qemu/osdep.h:787:9: warning: nested extern declaration of '__builtin_available' [-Wnested-externs] include/qemu/osdep.h:787:29: error: 'macOS' undeclared (first use in this function) 787 | if (__builtin_available(macOS 11.0, *)) { | ^~~~~ include/qemu/osdep.h:787:29: note: each undeclared identifier is reported only once for each function it appears in include/qemu/osdep.h:787:34: error: expected ')' before numeric constant 787 | if (__builtin_available(macOS 11.0, *)) { | ~ ^~~~~ | ) Beside, on macOS Catalina we get 2254 times: include/qemu/osdep.h:780:5: warning: 'pthread_jit_write_protect_np' is only available on macOS 11.0 or newer [-Wunguarded-availability-new] pthread_jit_write_protect_np(true); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fix by using a stricker toolchain version low range, replacing MAC_OS_X_VERSION_MAX_ALLOWED by MAC_OS_X_VERSION_MIN_REQUIRED. Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- include/qemu/osdep.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index c9ec7830c9..322103aadb 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -624,19 +624,15 @@ size_t qemu_get_host_physmem(void); * for the current thread. */ #if defined(MAC_OS_VERSION_11_0) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0 static inline void qemu_thread_jit_execute(void) { - if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(true); - } + pthread_jit_write_protect_np(true); } static inline void qemu_thread_jit_write(void) { - if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(false); - } + pthread_jit_write_protect_np(false); } #else static inline void qemu_thread_jit_write(void) {} From 30cfa50da53f60283e2e7f3bf0856189a06bb952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 17:25:03 +0100 Subject: [PATCH 13/21] meson: Resolve the entitlement.sh script once for good MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 235b523dba ("meson: Use find_program() to resolve the entitlement.sh script") didn't correctly fixed the issue, as the script is still resolved for each target. Move the check earlier, before processing each target. Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- meson.build | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 351f9f4360..6e8fa4ab31 100644 --- a/meson.build +++ b/meson.build @@ -3073,6 +3073,10 @@ common_all = static_library('common', feature_to_c = find_program('scripts/feature_to_c.sh') +if targetos == 'darwin' + entitlement = find_program('scripts/entitlement.sh') +endif + emulators = {} foreach target : target_dirs config_target = config_target_mak[target] @@ -3230,7 +3234,6 @@ foreach target : target_dirs install_input += meson.current_source_dir() / entitlements endif - entitlement = find_program('scripts/entitlement.sh') emulators += {exe['name'] : custom_target(exe['name'], input: build_input, output: exe['name'], From cf3ab8fe9e2360eace4c84b6779e0ab69516ae7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 16:14:35 +0100 Subject: [PATCH 14/21] meson: Log QEMU_CXXFLAGS content in summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 6e8fa4ab31..5fed23847b 100644 --- a/meson.build +++ b/meson.build @@ -3480,6 +3480,7 @@ if link_args.length() > 0 summary_info += {'LDFLAGS': ' '.join(link_args)} endif summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} +summary_info += {'QEMU_CXXFLAGS': config_host['QEMU_CXXFLAGS']} summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} summary_info += {'profiler': get_option('profiler')} summary_info += {'link-time optimization (LTO)': get_option('b_lto')} From 4cb37d1192e112159e3f8cb13de98a09fef502fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 16:15:13 +0100 Subject: [PATCH 15/21] configure: Pass filtered QEMU_OBJCFLAGS to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filter unsupported Objective-C options, to avoid 'unknown-warning-option' warnings when using Clang: [34/373] Compiling Objective-C object libcommon.fa.p/audio_coreaudio.m.o warning: unknown warning option '-Wold-style-declaration'; did you mean '-Wout-of-line-declaration'? [-Wunknown-warning-option] warning: unknown warning option '-Wimplicit-fallthrough=2'; did you mean '-Wimplicit-fallthrough'? [-Wunknown-warning-option] 2 warnings generated. Acked-by: Paolo Bonzini Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- configure | 23 +++++++++++++++++++++++ meson.build | 6 +++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 2bf40d9eeb..cd4946b43e 100755 --- a/configure +++ b/configure @@ -77,6 +77,7 @@ TMPB="qemu-conf" TMPC="${TMPDIR1}/${TMPB}.c" TMPO="${TMPDIR1}/${TMPB}.o" TMPCXX="${TMPDIR1}/${TMPB}.cxx" +TMPM="${TMPDIR1}/${TMPB}.m" TMPE="${TMPDIR1}/${TMPB}.exe" rm -f config.log @@ -148,6 +149,10 @@ do_cxx() { do_compiler "$cxx" $CPU_CFLAGS "$@" } +do_objc() { + do_compiler "$objcc" $CPU_CFLAGS "$@" +} + # Append $2 to the variable named $1, with space separation add_to() { eval $1=\${$1:+\"\$$1 \"}\$2 @@ -1445,10 +1450,27 @@ cc_has_warning_flag() { compile_prog "-Werror $optflag" "" } +objcc_has_warning_flag() { + cat > $TMPM <> $config_host_mak echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak +echo "QEMU_OBJCFLAGS=$QEMU_OBJCFLAGS" >> $config_host_mak echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak echo "GLIB_LIBS=$glib_libs" >> $config_host_mak echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak diff --git a/meson.build b/meson.build index 5fed23847b..cb24d30697 100644 --- a/meson.build +++ b/meson.build @@ -173,11 +173,13 @@ endif qemu_cflags = config_host['QEMU_CFLAGS'].split() qemu_cxxflags = config_host['QEMU_CXXFLAGS'].split() +qemu_objcflags = config_host['QEMU_OBJCFLAGS'].split() qemu_ldflags = config_host['QEMU_LDFLAGS'].split() if get_option('gprof') qemu_cflags += ['-p'] qemu_cxxflags += ['-p'] + qemu_objcflags += ['-p'] qemu_ldflags += ['-p'] endif @@ -216,8 +218,9 @@ if get_option('fuzzing') endif endif -add_global_arguments(qemu_cflags, native: false, language: ['c', 'objc']) +add_global_arguments(qemu_cflags, native: false, language: ['c']) add_global_arguments(qemu_cxxflags, native: false, language: ['cpp']) +add_global_arguments(qemu_objcflags, native: false, language: ['objc']) add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc']) if targetos == 'linux' @@ -3481,6 +3484,7 @@ if link_args.length() > 0 endif summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']} summary_info += {'QEMU_CXXFLAGS': config_host['QEMU_CXXFLAGS']} +summary_info += {'QEMU_OBJCFLAGS': config_host['QEMU_OBJCFLAGS']} summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']} summary_info += {'profiler': get_option('profiler')} summary_info += {'link-time optimization (LTO)': get_option('b_lto')} From 9459262dc4218110f4d3c5dce0b4fe43e1faffdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 15 Feb 2022 16:21:14 +0100 Subject: [PATCH 16/21] ui/cocoa: Constify qkeycode translation arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Peter Maydell Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- ui/cocoa.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index c88149852b..a66ba3d7b6 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -671,7 +671,7 @@ QemuCocoaView *cocoaView; /* translates Macintosh keycodes to QEMU's keysym */ - int without_control_translation[] = { + static const int without_control_translation[] = { [0 ... 0xff] = 0, // invalid key [kVK_UpArrow] = QEMU_KEY_UP, @@ -686,7 +686,7 @@ QemuCocoaView *cocoaView; [kVK_Delete] = QEMU_KEY_BACKSPACE, }; - int with_control_translation[] = { + static const int with_control_translation[] = { [0 ... 0xff] = 0, // invalid key [kVK_UpArrow] = QEMU_KEY_CTRL_UP, From 48941a52c2c3350b0c3dcdc1aba702def91d19a8 Mon Sep 17 00:00:00 2001 From: Carwyn Ellis Date: Sun, 2 Jan 2022 17:41:52 +0000 Subject: [PATCH 17/21] ui/cocoa: add option to disable left-command forwarding to guest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When switching between guest and host on a Mac using command-tab the command key is sent to the guest which can trigger functionality in the guest OS. Specifying left-command-key=off disables forwarding this key to the guest. Defaults to enabled. Also updated the cocoa display documentation to reference the new left-command-key option along with the existing show-cursor option. Signed-off-by: Carwyn Ellis Reviewed-by: Akihiko Odaki [PMD: Set QAPI structure @since tag to 7.0] Signed-off-by: Philippe Mathieu-Daudé --- qapi/ui.json | 18 ++++++++++++++++++ qemu-options.hx | 12 ++++++++++++ ui/cocoa.m | 8 +++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/qapi/ui.json b/qapi/ui.json index 4a13f883a3..4dea35a819 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1260,6 +1260,23 @@ { 'struct' : 'DisplayCurses', 'data' : { '*charset' : 'str' } } +## +# @DisplayCocoa: +# +# Cocoa display options. +# +# @left-command-key: Enable/disable forwarding of left command key to +# guest. Allows command-tab window switching on the +# host without sending this key to the guest when +# "off". Defaults to "on" +# +# Since: 7.0 +## +{ 'struct': 'DisplayCocoa', + 'data': { + '*left-command-key': 'bool' + } } + ## # @DisplayType: # @@ -1338,6 +1355,7 @@ 'discriminator' : 'type', 'data' : { 'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' }, + 'cocoa': { 'type': 'DisplayCocoa', 'if': 'CONFIG_COCOA' }, 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' }, 'egl-headless': { 'type': 'DisplayEGLHeadless', 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, diff --git a/qemu-options.hx b/qemu-options.hx index 5ce0ada75e..f464b2fe27 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1922,6 +1922,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, #if defined(CONFIG_DBUS_DISPLAY) "-display dbus[,addr=]\n" " [,gl=on|core|es|off][,rendernode=]\n" +#endif +#if defined(CONFIG_COCOA) + "-display cocoa[,show-cursor=on|off][,left-command-key=on|off]\n" #endif "-display none\n" " select display backend type\n" @@ -2009,6 +2012,15 @@ SRST ``charset=CP850`` for IBM CP850 encoding. The default is ``CP437``. + ``cocoa`` + Display video output in a Cocoa window. Mac only. This interface + provides drop-down menus and other UI elements to configure and + control the VM during runtime. Valid parameters are: + + ``show-cursor=on|off`` : Force showing the mouse cursor + + ``left-command-key=on|off`` : Disable forwarding left command key to host + ``egl-headless[,rendernode=]`` Offload all OpenGL operations to a local DRI device. For any graphical display, this display needs to be paired with either diff --git a/ui/cocoa.m b/ui/cocoa.m index a66ba3d7b6..1aa51c42dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -95,6 +95,7 @@ static DisplayChangeListener dcl = { }; static int last_buttons; static int cursor_hide = 1; +static int left_command_key_enabled = 1; static int gArgc; static char **gArgv; @@ -853,7 +854,8 @@ QemuCocoaView *cocoaView; /* Don't pass command key changes to guest unless mouse is grabbed */ case kVK_Command: if (isMouseGrabbed && - !!(modifiers & NSEventModifierFlagCommand)) { + !!(modifiers & NSEventModifierFlagCommand) && + left_command_key_enabled) { [self toggleKey:Q_KEY_CODE_META_L]; } break; @@ -2002,6 +2004,10 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) cursor_hide = 0; } + if (opts->u.cocoa.has_left_command_key && !opts->u.cocoa.left_command_key) { + left_command_key_enabled = 0; + } + // register vga output callbacks register_displaychangelistener(&dcl); From 69221df8cde644ce75053986b712c40a2a83966a Mon Sep 17 00:00:00 2001 From: Carwyn Ellis Date: Sun, 2 Jan 2022 17:41:53 +0000 Subject: [PATCH 18/21] ui/cocoa: release mouse when user switches away from QEMU window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This resolves an issue where using command-tab to switch between QEMU and other windows on the host can leave the mouse pointer visible. By releasing the mouse when the user switches away, the user must left click on the QEMU window when switching back in order to hide the pointer and return control to the guest. This appraoch ensures that the calls to NSCursor hide and unhide are always balanced and thus work correctly when invoked. Signed-off-by: Carwyn Ellis Reviewed-by: Akihiko Odaki Signed-off-by: Philippe Mathieu-Daudé --- ui/cocoa.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/cocoa.m b/ui/cocoa.m index 1aa51c42dc..d20c74d938 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1261,6 +1261,7 @@ QemuCocoaView *cocoaView; - (void) applicationWillResignActive: (NSNotification *)aNotification { COCOA_DEBUG("QemuCocoaAppController: applicationWillResignActive\n"); + [cocoaView ungrabMouse]; [cocoaView raiseAllKeys]; } @@ -2000,6 +2001,7 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) [(QemuCocoaAppController *)[[NSApplication sharedApplication] delegate] toggleFullScreen: nil]; }); } + if (opts->has_show_cursor && opts->show_cursor) { cursor_hide = 0; } From f844cdb997144a3fd83d7d18e32365fc6a1a8a1f Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Sun, 6 Mar 2022 21:11:18 +0900 Subject: [PATCH 19/21] ui/cocoa: capture all keys and combos when mouse is grabbed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applications such as Gnome may use Alt-Tab and Super-Tab for different purposes, some use Ctrl-arrows so we want to allow qemu to handle everything when it captures the mouse/keyboard. However, Mac OS handles some combos like Command-Tab and Ctrl-arrows at an earlier part of the event handling chain, not letting qemu see it. We add a global Event Tap that allows qemu to see all events when the mouse is grabbed. Note that this requires additional permissions. See: https://developer.apple.com/documentation/coregraphics/1454426-cgeventtapcreate?language=objc#discussion https://support.apple.com/en-in/guide/mac-help/mh32356/mac Acked-by: Markus Armbruster Signed-off-by: Gustavo Noronha Silva Message-Id: <20210713213200.2547-2-gustavo@noronha.dev.br> Signed-off-by: Akihiko Odaki Message-Id: <20220306121119.45631-2-akihiko.odaki@gmail.com> Reviewed-by: Will Cohen Signed-off-by: Philippe Mathieu-Daudé --- qapi/ui.json | 8 +++++- qemu-options.hx | 3 +++ ui/cocoa.m | 65 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index 4dea35a819..1d60d5fc78 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1270,11 +1270,17 @@ # host without sending this key to the guest when # "off". Defaults to "on" # +# @full-grab: Capture all key presses, including system combos. This +# requires accessibility permissions, since it performs +# a global grab on key events. (default: off) +# See https://support.apple.com/en-in/guide/mac-help/mh32356/mac +# # Since: 7.0 ## { 'struct': 'DisplayCocoa', 'data': { - '*left-command-key': 'bool' + '*left-command-key': 'bool', + '*full-grab': 'bool' } } ## diff --git a/qemu-options.hx b/qemu-options.hx index f464b2fe27..4395378bb8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1916,6 +1916,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, #if defined(CONFIG_CURSES) "-display curses[,charset=]\n" #endif +#if defined(CONFIG_COCOA) + "-display cocoa[,full_grab=on|off]\n" +#endif #if defined(CONFIG_OPENGL) "-display egl-headless[,rendernode=]\n" #endif diff --git a/ui/cocoa.m b/ui/cocoa.m index d20c74d938..b1250b7408 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -309,11 +309,13 @@ static void handleAnyDeviceErrors(Error * err) BOOL isMouseGrabbed; BOOL isFullscreen; BOOL isAbsoluteEnabled; + CFMachPortRef eventsTap; } - (void) switchSurface:(pixman_image_t *)image; - (void) grabMouse; - (void) ungrabMouse; - (void) toggleFullScreen:(id)sender; +- (void) setFullGrab:(id)sender; - (void) handleMonitorInput:(NSEvent *)event; - (bool) handleEvent:(NSEvent *)event; - (bool) handleEventLocked:(NSEvent *)event; @@ -336,6 +338,19 @@ static void handleAnyDeviceErrors(Error * err) QemuCocoaView *cocoaView; +static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEventRef cgEvent, void *userInfo) +{ + QemuCocoaView *cocoaView = userInfo; + NSEvent *event = [NSEvent eventWithCGEvent:cgEvent]; + if ([cocoaView isMouseGrabbed] && [cocoaView handleEvent:event]) { + COCOA_DEBUG("Global events tap: qemu handled the event, capturing!\n"); + return NULL; + } + COCOA_DEBUG("Global events tap: qemu did not handle the event, letting it through...\n"); + + return cgEvent; +} + @implementation QemuCocoaView - (id)initWithFrame:(NSRect)frameRect { @@ -361,6 +376,11 @@ QemuCocoaView *cocoaView; } qkbd_state_free(kbd); + + if (eventsTap) { + CFRelease(eventsTap); + } + [super dealloc]; } @@ -655,6 +675,36 @@ QemuCocoaView *cocoaView; } } +- (void) setFullGrab:(id)sender +{ + COCOA_DEBUG("QemuCocoaView: setFullGrab\n"); + + CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged); + eventsTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, + mask, handleTapEvent, self); + if (!eventsTap) { + warn_report("Could not create event tap, system key combos will not be captured.\n"); + return; + } else { + COCOA_DEBUG("Global events tap created! Will capture system key combos.\n"); + } + + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + if (!runLoop) { + warn_report("Could not obtain current CF RunLoop, system key combos will not be captured.\n"); + return; + } + + CFRunLoopSourceRef tapEventsSrc = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventsTap, 0); + if (!tapEventsSrc ) { + warn_report("Could not obtain current CF RunLoop, system key combos will not be captured.\n"); + return; + } + + CFRunLoopAddSource(runLoop, tapEventsSrc, kCFRunLoopDefaultMode); + CFRelease(tapEventsSrc); +} + - (void) toggleKey: (int)keycode { qkbd_state_key_event(kbd, keycode, !qkbd_state_key_get(kbd, keycode)); } @@ -1281,6 +1331,13 @@ QemuCocoaView *cocoaView; [cocoaView toggleFullScreen:sender]; } +- (void) setFullGrab:(id)sender +{ + COCOA_DEBUG("QemuCocoaAppController: setFullGrab\n"); + + [cocoaView setFullGrab:sender]; +} + /* Tries to find then open the specified filename */ - (void) openDocumentation: (NSString *) filename { @@ -1994,11 +2051,17 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) qemu_sem_wait(&app_started_sem); COCOA_DEBUG("cocoa_display_init: app start completed\n"); + QemuCocoaAppController *controller = (QemuCocoaAppController *)[[NSApplication sharedApplication] delegate]; /* if fullscreen mode is to be used */ if (opts->has_full_screen && opts->full_screen) { dispatch_async(dispatch_get_main_queue(), ^{ [NSApp activateIgnoringOtherApps: YES]; - [(QemuCocoaAppController *)[[NSApplication sharedApplication] delegate] toggleFullScreen: nil]; + [controller toggleFullScreen: nil]; + }); + } + if (opts->u.cocoa.has_full_grab && opts->u.cocoa.full_grab) { + dispatch_async(dispatch_get_main_queue(), ^{ + [controller setFullGrab: nil]; }); } From 4797adce5f0b7542c5aa4a83bdce7f0e63d6deae Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Sun, 6 Mar 2022 21:11:19 +0900 Subject: [PATCH 20/21] ui/cocoa: add option to swap Option and Command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Mac OS X the Option key maps to Alt and Command to Super/Meta. This change swaps them around so that Alt is the key closer to the space bar and Meta/Super is between Control and Alt, like on non-Mac keyboards. It is a cocoa display option, disabled by default. Acked-by: Markus Armbruster Signed-off-by: Gustavo Noronha Silva Message-Id: <20210713213200.2547-3-gustavo@noronha.dev.br> Signed-off-by: Akihiko Odaki Message-Id: <20220306121119.45631-3-akihiko.odaki@gmail.com> Reviewed-by: Will Cohen Signed-off-by: Philippe Mathieu-Daudé --- qapi/ui.json | 7 ++++++- qemu-options.hx | 2 +- ui/cocoa.m | 49 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index 1d60d5fc78..664da9e462 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1275,12 +1275,17 @@ # a global grab on key events. (default: off) # See https://support.apple.com/en-in/guide/mac-help/mh32356/mac # +# @swap-opt-cmd: Swap the Option and Command keys so that their key codes match +# their position on non-Mac keyboards and you can use Meta/Super +# and Alt where you expect them. (default: off) +# # Since: 7.0 ## { 'struct': 'DisplayCocoa', 'data': { '*left-command-key': 'bool', - '*full-grab': 'bool' + '*full-grab': 'bool', + '*swap-opt-cmd': 'bool' } } ## diff --git a/qemu-options.hx b/qemu-options.hx index 4395378bb8..58f2f76775 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1917,7 +1917,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, "-display curses[,charset=]\n" #endif #if defined(CONFIG_COCOA) - "-display cocoa[,full_grab=on|off]\n" + "-display cocoa[,full-grab=on|off][,swap-opt-cmd=on|off]\n" #endif #if defined(CONFIG_OPENGL) "-display egl-headless[,rendernode=]\n" diff --git a/ui/cocoa.m b/ui/cocoa.m index b1250b7408..cb6e7c41dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -96,6 +96,7 @@ static DisplayChangeListener dcl = { static int last_buttons; static int cursor_hide = 1; static int left_command_key_enabled = 1; +static bool swap_opt_cmd; static int gArgc; static char **gArgv; @@ -854,12 +855,22 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL_R, false); } if (!(modifiers & NSEventModifierFlagOption)) { - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); - qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + if (swap_opt_cmd) { + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + } else { + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + } } if (!(modifiers & NSEventModifierFlagCommand)) { - qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); - qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + if (swap_opt_cmd) { + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false); + } else { + qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false); + qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false); + } } switch ([event type]) { @@ -891,29 +902,44 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven case kVK_Option: if (!!(modifiers & NSEventModifierFlagOption)) { - [self toggleKey:Q_KEY_CODE_ALT]; + if (swap_opt_cmd) { + [self toggleKey:Q_KEY_CODE_META_L]; + } else { + [self toggleKey:Q_KEY_CODE_ALT]; + } } break; case kVK_RightOption: if (!!(modifiers & NSEventModifierFlagOption)) { - [self toggleKey:Q_KEY_CODE_ALT_R]; + if (swap_opt_cmd) { + [self toggleKey:Q_KEY_CODE_META_R]; + } else { + [self toggleKey:Q_KEY_CODE_ALT_R]; + } } break; /* Don't pass command key changes to guest unless mouse is grabbed */ case kVK_Command: if (isMouseGrabbed && - !!(modifiers & NSEventModifierFlagCommand) && - left_command_key_enabled) { - [self toggleKey:Q_KEY_CODE_META_L]; + !!(modifiers & NSEventModifierFlagCommand)) { + if (swap_opt_cmd) { + [self toggleKey:Q_KEY_CODE_ALT]; + } else { + [self toggleKey:Q_KEY_CODE_META_L]; + } } break; case kVK_RightCommand: if (isMouseGrabbed && !!(modifiers & NSEventModifierFlagCommand)) { - [self toggleKey:Q_KEY_CODE_META_R]; + if (swap_opt_cmd) { + [self toggleKey:Q_KEY_CODE_ALT_R]; + } else { + [self toggleKey:Q_KEY_CODE_META_R]; + } } break; } @@ -2068,6 +2094,9 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) if (opts->has_show_cursor && opts->show_cursor) { cursor_hide = 0; } + if (opts->u.cocoa.has_swap_opt_cmd) { + swap_opt_cmd = opts->u.cocoa.swap_opt_cmd; + } if (opts->u.cocoa.has_left_command_key && !opts->u.cocoa.left_command_key) { left_command_key_enabled = 0; From c82b7ef16f3efa59e28f821f25a9c084ef84ea9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 14 Mar 2022 18:28:35 +0100 Subject: [PATCH 21/21] MAINTAINERS: Volunteer to maintain Darwin-based hosts support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While I am not an experienced Darwin OS user, I now have to use a macOS based workstation and alike CI, meaning I should easily spot regressions and test fixes. I therefore volunteer to collect Darwin related patches and keep QEMU in good state on macOS, and to some extent iOS. Cc: Gerd Hoffmann Cc: Christian Schoenebeck Cc: Akihiko Odaki Cc: Joelle van Dyne Cc: Daniel P. Berrangé Cc: Peter Maydell Acked-by: Gerd Hoffmann Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f2e9ce1da2..caea42c259 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -548,6 +548,12 @@ F: include/*/*win32* X: qga/*win32* F: qemu.nsi +Darwin (macOS, iOS) +M: Philippe Mathieu-Daudé +S: Odd Fixes +F: .gitlab-ci.d/cirrus/macos-* +F: */*.m + Alpha Machines -------------- M: Richard Henderson @@ -2414,6 +2420,7 @@ F: audio/alsaaudio.c Core Audio framework backend M: Gerd Hoffmann +M: Philippe Mathieu-Daudé R: Christian Schoenebeck R: Akihiko Odaki S: Odd Fixes @@ -2671,6 +2678,7 @@ F: util/drm.c Cocoa graphics M: Peter Maydell +M: Philippe Mathieu-Daudé R: Akihiko Odaki S: Odd Fixes F: ui/cocoa.m