diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-03-15 18:58:41 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-03-15 18:58:41 +0000 |
commit | 22a3a45ade8d331f3c318afeb0374c94129e55b4 (patch) | |
tree | 046a894e945c680c58429b345969603c569373b8 | |
parent | e2fb7d8aa218256793df99571d16f92074258447 (diff) | |
parent | c82b7ef16f3efa59e28f821f25a9c084ef84ea9d (diff) |
Merge tag 'darwin-20220315' of https://github.com/philmd/qemu into staging
Darwin-based host patches
- Remove various build warnings
- Fix building with modules on macOS
- Fix mouse/keyboard GUI interactions
# gpg: Signature made Tue 15 Mar 2022 12:52:19 GMT
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'darwin-20220315' of https://github.com/philmd/qemu: (21 commits)
MAINTAINERS: Volunteer to maintain Darwin-based hosts support
ui/cocoa: add option to swap Option and Command
ui/cocoa: capture all keys and combos when mouse is grabbed
ui/cocoa: release mouse when user switches away from QEMU window
ui/cocoa: add option to disable left-command forwarding to guest
ui/cocoa: Constify qkeycode translation arrays
configure: Pass filtered QEMU_OBJCFLAGS to meson
meson: Log QEMU_CXXFLAGS content in summary
meson: Resolve the entitlement.sh script once for good
osdep: Avoid using Clang-specific __builtin_available()
audio: Rename coreaudio extension to use Objective-C compiler
coreaudio: Always return 0 in handle_voice_change
audio: Log context for audio bug
audio/dbus: Fix building with modules on macOS
audio/coreaudio: Remove a deprecation warning on macOS 12
block/file-posix: Remove a deprecation warning on macOS 12
hvf: Remove deprecated hv_vcpu_flush() calls
hvf: Make hvf_get_segments() / hvf_put_segments() local
hvf: Use standard CR0 and CR4 register definitions
tests/fp/berkeley-testfloat-3: Ignore ignored #pragma directives
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | audio/audio.c | 25 | ||||
-rw-r--r-- | audio/audio_template.h | 27 | ||||
-rw-r--r-- | audio/coreaudio.m (renamed from audio/coreaudio.c) | 23 | ||||
-rw-r--r-- | audio/meson.build | 4 | ||||
-rw-r--r-- | block/file-posix.c | 14 | ||||
-rwxr-xr-x | configure | 31 | ||||
-rw-r--r-- | include/qemu/osdep.h | 10 | ||||
-rw-r--r-- | meson.build | 17 | ||||
-rw-r--r-- | qapi/ui.json | 29 | ||||
-rw-r--r-- | qemu-options.hx | 15 | ||||
-rw-r--r-- | target/i386/hvf/vmx.h | 19 | ||||
-rw-r--r-- | target/i386/hvf/x86.c | 6 | ||||
-rw-r--r-- | target/i386/hvf/x86.h | 34 | ||||
-rw-r--r-- | target/i386/hvf/x86_mmu.c | 2 | ||||
-rw-r--r-- | target/i386/hvf/x86_task.c | 4 | ||||
-rw-r--r-- | target/i386/hvf/x86hvf.c | 6 | ||||
-rw-r--r-- | target/i386/hvf/x86hvf.h | 2 | ||||
-rw-r--r-- | tests/fp/meson.build | 5 | ||||
-rw-r--r-- | ui/cocoa.m | 122 |
20 files changed, 283 insertions, 120 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index b976a942dc..9aed5f3e04 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é <f4bug@amsat.org> +S: Odd Fixes +F: .gitlab-ci.d/cirrus/macos-* +F: */*.m + Alpha Machines -------------- M: Richard Henderson <richard.henderson@linaro.org> @@ -2414,6 +2420,7 @@ F: audio/alsaaudio.c Core Audio framework backend M: Gerd Hoffmann <kraxel@redhat.com> +M: Philippe Mathieu-Daudé <f4bug@amsat.org> R: Christian Schoenebeck <qemu_oss@crudebyte.com> R: Akihiko Odaki <akihiko.odaki@gmail.com> S: Odd Fixes @@ -2671,6 +2678,7 @@ F: util/drm.c Cocoa graphics M: Peter Maydell <peter.maydell@linaro.org> +M: Philippe Mathieu-Daudé <f4bug@amsat.org> R: Akihiko Odaki <akihiko.odaki@gmail.com> S: Odd Fixes F: ui/cocoa.m 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)) { diff --git a/audio/coreaudio.c b/audio/coreaudio.m index 0f19d0ce01..3186b68474 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.m @@ -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, @@ -540,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(); @@ -549,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, diff --git a/audio/meson.build b/audio/meson.build index 0ac3791d0b..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 = {} @@ -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 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", @@ -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 @@ -285,6 +290,7 @@ done EXTRA_CFLAGS="" EXTRA_CXXFLAGS="" +EXTRA_OBJCFLAGS="" EXTRA_LDFLAGS="" xen_ctrl_version="$default_feature" @@ -366,9 +372,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 +757,8 @@ for opt do ;; --extra-cxxflags=*) ;; + --extra-objcflags=*) + ;; --extra-ldflags=*) ;; --enable-debug-info) @@ -1172,6 +1183,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 @@ -1438,10 +1450,27 @@ cc_has_warning_flag() { compile_prog "-Werror $optflag" "" } +objcc_has_warning_flag() { + cat > $TMPM <<EOF +int main(void) { return 0; } +EOF + + # Use the positive sense of the flag when testing for -Wno-wombat + # support (gcc will happily accept the -Wno- form of unknown + # warning options). + optflag="$(echo $1 | sed -e 's/^-Wno-/-W/')" + do_objc -Werror $optflag \ + $OBJCFLAGS $EXTRA_OBJCFLAGS $CONFIGURE_OBJCFLAGS $QEMU_OBJCFLAGS \ + -o $TMPE $TMPM $QEMU_LDFLAGS +} + for flag in $gcc_flags; do if cc_has_warning_flag $flag ; then QEMU_CFLAGS="$QEMU_CFLAGS $flag" fi + if objcc_has_warning_flag $flag ; then + QEMU_OBJCFLAGS="$QEMU_OBJCFLAGS $flag" + fi done if test "$stack_protector" != "no"; then @@ -2983,6 +3012,7 @@ echo "LD=$ld" >> $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 @@ -3137,6 +3167,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/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) {} diff --git a/meson.build b/meson.build index ad4327888f..bae62efc9c 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' @@ -3076,6 +3079,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] @@ -3233,7 +3240,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'], @@ -3470,11 +3476,18 @@ 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)} 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')} diff --git a/qapi/ui.json b/qapi/ui.json index 4a13f883a3..664da9e462 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1261,6 +1261,34 @@ '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" +# +# @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 +# +# @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', + '*swap-opt-cmd': 'bool' + } } + +## # @DisplayType: # # Display (user interface) type. @@ -1338,6 +1366,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..58f2f76775 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=<encoding>]\n" #endif +#if defined(CONFIG_COCOA) + "-display cocoa[,full-grab=on|off][,swap-opt-cmd=on|off]\n" +#endif #if defined(CONFIG_OPENGL) "-display egl-headless[,rendernode=<file>]\n" #endif @@ -1923,6 +1926,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, "-display dbus[,addr=<dbusaddr>]\n" " [,gl=on|core|es|off][,rendernode=<file>]\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" " The default display is equivalent to\n " @@ -2009,6 +2015,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=<file>]`` Offload all OpenGL operations to a local DRI device. For any graphical display, this display needs to be paired with either diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index 6df87116f6..573ddc33c0 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,23 +156,21 @@ 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); } 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); } static inline void macvm_set_rip(CPUState *cpu, uint64_t rip) 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..d24daf6a41 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -174,12 +174,12 @@ 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); 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 05ec1bddc4..bec9fc5814 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; @@ -125,8 +125,6 @@ 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) @@ -166,7 +164,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 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', diff --git a/ui/cocoa.m b/ui/cocoa.m index c88149852b..cb6e7c41dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -95,6 +95,8 @@ 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; @@ -308,11 +310,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; @@ -335,6 +339,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 { @@ -360,6 +377,11 @@ QemuCocoaView *cocoaView; } qkbd_state_free(kbd); + + if (eventsTap) { + CFRelease(eventsTap); + } + [super dealloc]; } @@ -654,6 +676,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)); } @@ -671,7 +723,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 +738,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, @@ -803,12 +855,22 @@ QemuCocoaView *cocoaView; 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]) { @@ -840,13 +902,21 @@ QemuCocoaView *cocoaView; 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; @@ -854,14 +924,22 @@ QemuCocoaView *cocoaView; case kVK_Command: if (isMouseGrabbed && !!(modifiers & NSEventModifierFlagCommand)) { - [self toggleKey:Q_KEY_CODE_META_L]; + 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; } @@ -1259,6 +1337,7 @@ QemuCocoaView *cocoaView; - (void) applicationWillResignActive: (NSNotification *)aNotification { COCOA_DEBUG("QemuCocoaAppController: applicationWillResignActive\n"); + [cocoaView ungrabMouse]; [cocoaView raiseAllKeys]; } @@ -1278,6 +1357,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 { @@ -1991,16 +2077,30 @@ 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]; }); } + 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; + } // register vga output callbacks register_displaychangelistener(&dcl); |