diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2024-03-26 15:50:29 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2024-03-26 15:50:29 +0000 |
commit | 38a23eb35c4799d6cad88f81a5556f5d424b3a07 (patch) | |
tree | 343875e1151fbd0e69c8713d1df1e5693600398f | |
parent | 5107022a616247216a7f7338bd7c62b4399d89eb (diff) | |
parent | ccebb9ae352eea63cb1491cb829e4cd0f7576f1c (diff) |
Merge tag 'hw-misc-20240326' of https://github.com/philmd/qemu into staging
Misc HW patch queue
[hw]
- Do not silently overwrite 'io_timeout' property in scsi-generic (Lorenz)
- Propagate period when enabling a clock in stm32l4x5 mux (Arnaud, Phil)
- Add missing smbios_get_table_legacy() stub (Igor)
- Append a space in gpa2hva() HMP error message (Yao)
- Fix compiler warning in 'execlog' plugin (Yao)
[target]
- i386: Enable page walking from MMIO memory (Gregory, Jonathan)
- tricore: Use correct string format in cpu_tlb_fill (Phil)
[docs]
- Fix formatting in amigang.rst (Zoltan)
[ui]
- Fix cocoa regression in platform fullscreen toggling (Akihiko)
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmYC7QoACgkQ4+MsLN6t
# wN4WIw//cLw1caDa8ki3htGWGVI2P/QFdsvId7ah4Iul7znf6NWUORDBjvIvLpaF
# sesPF7BRQ/qJFT5ttB8DsKc1IHw3IASAGL/NK3i7v9GkRiBJNJvQRO2rVfNmXvN8
# ++AZ/J+Y1OZ4Y1hcxXGUVIpwKzndR5Oz9zNXQ+C0CQqYljwxC3huB3m6C7vKOgeq
# SNKVw/hrTBYLzyvooKqLb6Xual2+olSwc2/BwqUOOCP6Y1HmgQeWy5ckJqsuVS2T
# 5q5VtkduBCsUhgmflsLF3LCKrNTQUw+jOAGH2gyRvXMjmvwCmNy5xo8eOD0iTwXb
# +Ffp/kfqm2N1QwNWcBi39+BU+Plti03mnL7C9jNzaEBaQ9Q7wMNqASN0daHSk3vh
# 4Vw/FsaUJAohInKYghCgO0fUVpeLis+8p5lDD7QwAL9tiYk7/tgrbtyNLb+m/3P9
# pPNGt9Fnijg+/zDDfjVYwtDMRbL0df7SqTjhJW3TIQ+d83tmoVuCDmBysEXywzSt
# 5e4yyjDf8q1C23yipK9I84wuvWjfIDYIPSUzCKaZYf4xbdx7GyNaOoOqWZYpordD
# ua/4hRuQ4AcDuCe3XBKsmAex6wpYodjnfEi5Y5uV8vyPfeiVQodY/07pok/NZjEL
# tUNy3EkQFqXxT1ctT7FhN2eh6WjSo0SJFtIjVDarJ0mUkS4VXgM=
# =ccz/
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 26 Mar 2024 15:43:06 GMT
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'hw-misc-20240326' of https://github.com/philmd/qemu:
ui/cocoa: Use NSTrackingInVisibleRect
ui/cocoa: Resize window after toggling zoom-to-fit
ui/cocoa: Fix aspect ratio
hw/smbios: add stub for smbios_get_table_legacy()
contrib/plugins/execlog: Fix compiler warning
docs/system/ppc/amigang.rst: Fix formatting
hw/misc/stm32l4x5_rcc: Propagate period when enabling a clock
hw/misc/stm32l4x5_rcc: Inline clock_update() in clock_mux_update()
hw/clock: Let clock_set_mul_div() return a boolean value
target/tricore/helper: Use correct string format in cpu_tlb_fill()
monitor/hmp-cmds-target: Append a space in error message in gpa2hva()
hw/scsi/scsi-generic: Fix io_timeout property not applying
target/i386/tcg: Enable page walking from MMIO memory
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | contrib/plugins/execlog.c | 24 | ||||
-rw-r--r-- | docs/devel/clocks.rst | 4 | ||||
-rw-r--r-- | docs/system/ppc/amigang.rst | 4 | ||||
-rw-r--r-- | hw/core/clock.c | 8 | ||||
-rw-r--r-- | hw/misc/stm32l4x5_rcc.c | 9 | ||||
-rw-r--r-- | hw/scsi/scsi-generic.c | 1 | ||||
-rw-r--r-- | hw/smbios/smbios_legacy_stub.c | 5 | ||||
-rw-r--r-- | include/hw/clock.h | 4 | ||||
-rw-r--r-- | monitor/hmp-cmds-target.c | 2 | ||||
-rw-r--r-- | target/i386/tcg/sysemu/excp_helper.c | 57 | ||||
-rw-r--r-- | target/tricore/helper.c | 4 | ||||
-rw-r--r-- | ui/cocoa.m | 90 |
12 files changed, 137 insertions, 75 deletions
diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index a1dfd59ab7..fab18113d4 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -311,6 +311,24 @@ static Register *init_vcpu_register(qemu_plugin_reg_descriptor *desc) return reg; } +/* + * g_pattern_match_string has been deprecated in Glib since 2.70 and + * will complain about it if you try to use it. Fortunately the + * signature of both functions is the same making it easy to work + * around. + */ +static inline +gboolean g_pattern_spec_match_string_qemu(GPatternSpec *pspec, + const gchar *string) +{ +#if GLIB_CHECK_VERSION(2, 70, 0) + return g_pattern_spec_match_string(pspec, string); +#else + return g_pattern_match_string(pspec, string); +#endif +}; +#define g_pattern_spec_match_string(p, s) g_pattern_spec_match_string_qemu(p, s) + static GPtrArray *registers_init(int vcpu_index) { g_autoptr(GPtrArray) registers = g_ptr_array_new(); @@ -327,8 +345,8 @@ static GPtrArray *registers_init(int vcpu_index) for (int p = 0; p < rmatches->len; p++) { g_autoptr(GPatternSpec) pat = g_pattern_spec_new(rmatches->pdata[p]); g_autofree gchar *rd_lower = g_utf8_strdown(rd->name, -1); - if (g_pattern_match_string(pat, rd->name) || - g_pattern_match_string(pat, rd_lower)) { + if (g_pattern_spec_match_string(pat, rd->name) || + g_pattern_spec_match_string(pat, rd_lower)) { Register *reg = init_vcpu_register(rd); g_ptr_array_add(registers, reg); @@ -336,7 +354,7 @@ static GPtrArray *registers_init(int vcpu_index) if (disas_assist) { g_mutex_lock(&add_reg_name_lock); if (!g_ptr_array_find(all_reg_names, reg->name, NULL)) { - g_ptr_array_add(all_reg_names, reg->name); + g_ptr_array_add(all_reg_names, (gpointer)reg->name); } g_mutex_unlock(&add_reg_name_lock); } diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst index c4d14bde04..b2d1148cdb 100644 --- a/docs/devel/clocks.rst +++ b/docs/devel/clocks.rst @@ -279,6 +279,10 @@ You can change the multiplier and divider of a clock at runtime, so you can use this to model clock controller devices which have guest-programmable frequency multipliers or dividers. +Similary to ``clock_set()``, ``clock_set_mul_div()`` returns ``true`` if +the clock state was modified; that is, if the multiplier or the diviser +or both were changed by the call. + Note that ``clock_set_mul_div()`` does not automatically call ``clock_propagate()``. If you make a runtime change to the multiplier or divider you must call clock_propagate() yourself. diff --git a/docs/system/ppc/amigang.rst b/docs/system/ppc/amigang.rst index ba1a3d80b9..e2c9cb74b7 100644 --- a/docs/system/ppc/amigang.rst +++ b/docs/system/ppc/amigang.rst @@ -16,7 +16,7 @@ firmware to support AmigaOS 4. Emulated devices ---------------- - * PowerPC 7457 CPU (can also use``-cpu g3, 750cxe, 750fx`` or ``750gx``) + * PowerPC 7457 CPU (can also use ``-cpu g3, 750cxe, 750fx`` or ``750gx``) * Articia S north bridge * VIA VT82C686B south bridge * PCI VGA compatible card (guests may need other card instead) @@ -73,7 +73,7 @@ https://www.powerdeveloper.org/platforms/pegasos/schematics. Emulated devices ---------------- - * PowerPC 7457 CPU (can also use``-cpu g3`` or ``750cxe``) + * PowerPC 7457 CPU (can also use ``-cpu g3`` or ``750cxe``) * Marvell MV64361 Discovery II north bridge * VIA VT8231 south bridge * PCI VGA compatible card (guests may need other card instead) diff --git a/hw/core/clock.c b/hw/core/clock.c index d82e44cd1a..a19c7db7df 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -143,14 +143,20 @@ char *clock_display_freq(Clock *clk) return freq_to_str(clock_get_hz(clk)); } -void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider) +bool clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider) { assert(divider != 0); + if (clk->multiplier == multiplier && clk->divider == divider) { + return false; + } + trace_clock_set_mul_div(CLOCK_PATH(clk), clk->multiplier, multiplier, clk->divider, divider); clk->multiplier = multiplier; clk->divider = divider; + + return true; } static void clock_initfn(Object *obj) diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index bc2d63528b..ed2dbd9dc3 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -48,6 +48,8 @@ static void clock_mux_update(RccClockMuxState *mux, bool bypass_source) uint64_t src_freq; Clock *current_source = mux->srcs[mux->src]; uint32_t freq_multiplier = 0; + bool clk_changed = false; + /* * To avoid rounding errors, we use the clock period instead of the * frequency. @@ -59,8 +61,11 @@ static void clock_mux_update(RccClockMuxState *mux, bool bypass_source) freq_multiplier = mux->divider; } - clock_set_mul_div(mux->out, freq_multiplier, mux->multiplier); - clock_update(mux->out, clock_get(current_source)); + clk_changed |= clock_set_mul_div(mux->out, freq_multiplier, mux->multiplier); + clk_changed |= clock_set(mux->out, clock_get(current_source)); + if (clk_changed) { + clock_propagate(mux->out); + } src_freq = clock_get_hz(current_source); /* TODO: can we simply detect if the config changed so that we reduce log spam ? */ diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index b7b04e1d63..ee945f87e3 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -752,7 +752,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) /* Only used by scsi-block, but initialize it nevertheless to be clean. */ s->default_scsi_version = -1; - s->io_timeout = DEFAULT_IO_TIMEOUT; scsi_generic_read_device_inquiry(s); } diff --git a/hw/smbios/smbios_legacy_stub.c b/hw/smbios/smbios_legacy_stub.c index f29b15316c..7d593dca98 100644 --- a/hw/smbios/smbios_legacy_stub.c +++ b/hw/smbios/smbios_legacy_stub.c @@ -13,3 +13,8 @@ void smbios_add_usr_blob_size(size_t size) { } + +uint8_t *smbios_get_table_legacy(size_t *length, Error **errp) +{ + g_assert_not_reached(); +} diff --git a/include/hw/clock.h b/include/hw/clock.h index bb12117f67..eb58599131 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -357,6 +357,8 @@ char *clock_display_freq(Clock *clk); * @multiplier: multiplier value * @divider: divider value * + * @return: true if the clock is changed. + * * By default, a Clock's children will all run with the same period * as their parent. This function allows you to adjust the multiplier * and divider used to derive the child clock frequency. @@ -374,6 +376,6 @@ char *clock_display_freq(Clock *clk); * Note that this function does not call clock_propagate(); the * caller should do that if necessary. */ -void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider); +bool clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider); #endif /* QEMU_HW_CLOCK_H */ diff --git a/monitor/hmp-cmds-target.c b/monitor/hmp-cmds-target.c index 9338ae8440..ff01cf9d8d 100644 --- a/monitor/hmp-cmds-target.c +++ b/monitor/hmp-cmds-target.c @@ -261,7 +261,7 @@ void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp) } if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) { - error_setg(errp, "Memory at address 0x%" HWADDR_PRIx "is not RAM", addr); + error_setg(errp, "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr); memory_region_unref(mrs.mr); return NULL; } diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 8f7011d966..7a57b7dd10 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -59,14 +59,14 @@ typedef struct PTETranslate { hwaddr gaddr; } PTETranslate; -static bool ptw_translate(PTETranslate *inout, hwaddr addr) +static bool ptw_translate(PTETranslate *inout, hwaddr addr, uint64_t ra) { CPUTLBEntryFull *full; int flags; inout->gaddr = addr; flags = probe_access_full(inout->env, addr, 0, MMU_DATA_STORE, - inout->ptw_idx, true, &inout->haddr, &full, 0); + inout->ptw_idx, true, &inout->haddr, &full, ra); if (unlikely(flags & TLB_INVALID_MASK)) { TranslateFault *err = inout->err; @@ -82,20 +82,20 @@ static bool ptw_translate(PTETranslate *inout, hwaddr addr) return true; } -static inline uint32_t ptw_ldl(const PTETranslate *in) +static inline uint32_t ptw_ldl(const PTETranslate *in, uint64_t ra) { if (likely(in->haddr)) { return ldl_p(in->haddr); } - return cpu_ldl_mmuidx_ra(in->env, in->gaddr, in->ptw_idx, 0); + return cpu_ldl_mmuidx_ra(in->env, in->gaddr, in->ptw_idx, ra); } -static inline uint64_t ptw_ldq(const PTETranslate *in) +static inline uint64_t ptw_ldq(const PTETranslate *in, uint64_t ra) { if (likely(in->haddr)) { return ldq_p(in->haddr); } - return cpu_ldq_mmuidx_ra(in->env, in->gaddr, in->ptw_idx, 0); + return cpu_ldq_mmuidx_ra(in->env, in->gaddr, in->ptw_idx, ra); } /* @@ -132,7 +132,8 @@ static inline bool ptw_setl(const PTETranslate *in, uint32_t old, uint32_t set) } static bool mmu_translate(CPUX86State *env, const TranslateParams *in, - TranslateResult *out, TranslateFault *err) + TranslateResult *out, TranslateFault *err, + uint64_t ra) { const target_ulong addr = in->addr; const int pg_mode = in->pg_mode; @@ -164,11 +165,11 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 5 */ pte_addr = (in->cr3 & ~0xfff) + (((addr >> 48) & 0x1ff) << 3); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } restart_5: - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -188,11 +189,11 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 4 */ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 39) & 0x1ff) << 3); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } restart_4: - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -208,11 +209,11 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 3 */ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } restart_3_lma: - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -235,12 +236,12 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 3 */ pte_addr = (in->cr3 & 0xffffffe0ULL) + ((addr >> 27) & 0x18); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } rsvd_mask |= PG_HI_USER_MASK; restart_3_nolma: - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -257,11 +258,11 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 2 */ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } restart_2_pae: - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -283,10 +284,10 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 1 */ pte_addr = (pte & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } - pte = ptw_ldq(&pte_trans); + pte = ptw_ldq(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -301,11 +302,11 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 2 */ pte_addr = (in->cr3 & 0xfffff000ULL) + ((addr >> 20) & 0xffc); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } restart_2_nopae: - pte = ptw_ldl(&pte_trans); + pte = ptw_ldl(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -330,10 +331,10 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in, * Page table level 1 */ pte_addr = (pte & ~0xfffu) + ((addr >> 10) & 0xffc); - if (!ptw_translate(&pte_trans, pte_addr)) { + if (!ptw_translate(&pte_trans, pte_addr, ra)) { return false; } - pte = ptw_ldl(&pte_trans); + pte = ptw_ldl(&pte_trans, ra); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; } @@ -526,7 +527,8 @@ static G_NORETURN void raise_stage2(CPUX86State *env, TranslateFault *err, static bool get_physical_address(CPUX86State *env, vaddr addr, MMUAccessType access_type, int mmu_idx, - TranslateResult *out, TranslateFault *err) + TranslateResult *out, TranslateFault *err, + uint64_t ra) { TranslateParams in; bool use_stage2 = env->hflags2 & HF2_NPT_MASK; @@ -546,7 +548,7 @@ static bool get_physical_address(CPUX86State *env, vaddr addr, env->nested_pg_mode & PG_MODE_LMA ? MMU_USER64_IDX : MMU_USER32_IDX; in.ptw_idx = MMU_PHYS_IDX; - if (!mmu_translate(env, &in, out, err)) { + if (!mmu_translate(env, &in, out, err, ra)) { err->stage2 = S2_GPA; return false; } @@ -577,7 +579,7 @@ static bool get_physical_address(CPUX86State *env, vaddr addr, return false; } } - return mmu_translate(env, &in, out, err); + return mmu_translate(env, &in, out, err, ra); } break; } @@ -597,7 +599,8 @@ bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, TranslateResult out; TranslateFault err; - if (get_physical_address(env, addr, access_type, mmu_idx, &out, &err)) { + if (get_physical_address(env, addr, access_type, mmu_idx, &out, &err, + retaddr)) { /* * Even if 4MB pages, we map only one 4KB page in the cache to * avoid filling it too fast. diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 6d9e80cc0c..76bd226370 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -76,9 +76,9 @@ bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ret = get_physical_address(env, &physical, &prot, address, rw, mmu_idx); - qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical " + qemu_log_mask(CPU_LOG_MMU, "%s address=0x%" VADDR_PRIx " ret %d physical " HWADDR_FMT_plx " prot %d\n", - __func__, (target_ulong)address, ret, physical, prot); + __func__, address, ret, physical, prot); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, diff --git a/ui/cocoa.m b/ui/cocoa.m index 810751cf26..25e0db9dd0 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -307,7 +307,6 @@ static void handleAnyDeviceErrors(Error * err) */ @interface QemuCocoaView : NSView { - NSTrackingArea *trackingArea; QEMUScreen screen; pixman_image_t *pixman_image; BOOL isMouseGrabbed; @@ -359,6 +358,19 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven self = [super initWithFrame:frameRect]; if (self) { + NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow | + NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingInVisibleRect; + + NSTrackingArea *trackingArea = + [[NSTrackingArea alloc] initWithRect:CGRectZero + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; + [trackingArea release]; screen.width = frameRect.size.width; screen.height = frameRect.size.height; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0 @@ -389,41 +401,9 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven return YES; } -- (void) removeTrackingRect -{ - if (trackingArea) { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; - trackingArea = nil; - } -} - -- (void) frameUpdated -{ - [self removeTrackingRect]; - - if ([self window]) { - NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow | - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved; - trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame] - options:options - owner:self - userInfo:nil]; - [self addTrackingArea:trackingArea]; - [self updateUIInfo]; - } -} - - (void) viewDidMoveToWindow { [self resizeWindow]; - [self frameUpdated]; -} - -- (void) viewWillMoveToWindow:(NSWindow *)newWindow -{ - [self removeTrackingRect]; } - (void) selectConsoleLocked:(unsigned int)index @@ -519,6 +499,43 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven } } +- (NSSize)fixAspectRatio:(NSSize)max +{ + NSSize scaled; + NSSize fixed; + + scaled.width = screen.width * max.height; + scaled.height = screen.height * max.width; + + /* + * Here screen is our guest's output size, and max is the size of the + * largest possible area of the screen we can display on. + * We want to scale up (screen.width x screen.height) by either: + * 1) max.height / screen.height + * 2) max.width / screen.width + * With the first scale factor the scale will result in an output height of + * max.height (i.e. we will fill the whole height of the available screen + * space and have black bars left and right) and with the second scale + * factor the scaling will result in an output width of max.width (i.e. we + * fill the whole width of the available screen space and have black bars + * top and bottom). We need to pick whichever keeps the whole of the guest + * output on the screen, which is to say the smaller of the two scale + * factors. + * To avoid doing more division than strictly necessary, instead of directly + * comparing scale factors 1 and 2 we instead calculate and compare those + * two scale factors multiplied by (screen.height * screen.width). + */ + if (scaled.width < scaled.height) { + fixed.width = scaled.width / screen.height; + fixed.height = max.height; + } else { + fixed.width = max.width; + fixed.height = scaled.height / screen.width; + } + + return fixed; +} + - (NSSize) screenSafeAreaSize { NSSize size = [[[self window] screen] frame].size; @@ -536,8 +553,10 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [[self window] setContentSize:NSMakeSize(screen.width, screen.height)]; [[self window] center]; } else if ([[self window] styleMask] & NSWindowStyleMaskFullScreen) { - [[self window] setContentSize:[self screenSafeAreaSize]]; + [[self window] setContentSize:[self fixAspectRatio:[self screenSafeAreaSize]]]; [[self window] center]; + } else { + [[self window] setContentSize:[self fixAspectRatio:[self frame].size]]; } } @@ -1275,7 +1294,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven - (void)windowDidResize:(NSNotification *)notification { [cocoaView updateBounds]; - [cocoaView frameUpdated]; + [cocoaView updateUIInfo]; } /* Called when the user clicks on a window's close button */ @@ -1369,6 +1388,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [[cocoaView window] setStyleMask:styleMask]; [sender setState:styleMask & NSWindowStyleMaskResizable ? NSControlStateValueOn : NSControlStateValueOff]; + [cocoaView resizeWindow]; } - (void)toggleZoomInterpolation:(id) sender |