Skip to content

Commit 5bef309

Browse files
committed
Add scroll wheel zoom support and dynamic scrollbar management
When zoom mode is enabled, scrollbars now appear and support mouse wheel zooming with Cmd+scroll or Opt+scroll. When zoom is disabled, scrollbars are hidden and the view fits the window. This makes zoom functional on devices without trackpads.
1 parent 8e62f85 commit 5bef309

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

virtualization_view.m

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,13 @@ - (void)setupGraphicWindow
416416
return event;
417417
}];
418418

419+
// Add scroll wheel event monitor for zoom functionality
420+
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel
421+
handler:^NSEvent *(NSEvent *event) {
422+
[self handleScrollWheel:event];
423+
return event;
424+
}];
425+
419426
// Create scroll view for the virtual machine view
420427
NSScrollView *scrollView = [self createScrollViewForVirtualMachineView:_virtualMachineView];
421428
[_window setContentView:scrollView];
@@ -638,6 +645,7 @@ - (void)showErrorAlertWithMessage:(NSString *)message error:(NSError *)error
638645
- (void)toggleZoomMode:(id)sender
639646
{
640647
_isZoomEnabled = !_isZoomEnabled;
648+
NSScrollView *scrollView = (NSScrollView *)_window.contentView;
641649

642650
// Reset zoom when zoom mode is disabled.
643651
if (!_isZoomEnabled) {
@@ -646,7 +654,20 @@ - (void)toggleZoomMode:(id)sender
646654
[context setDuration:0.3];
647655
[[_window.contentView animator] setMagnification:1.0];
648656
}
649-
completionHandler:nil];
657+
completionHandler:^{
658+
// Hide scrollers when zoom is disabled
659+
if ([scrollView isKindOfClass:[NSScrollView class]]) {
660+
scrollView.hasVerticalScroller = NO;
661+
scrollView.hasHorizontalScroller = NO;
662+
}
663+
}];
664+
} else {
665+
// Show scrollers when zoom is enabled (they'll auto-hide when not needed)
666+
if ([scrollView isKindOfClass:[NSScrollView class]]) {
667+
scrollView.hasVerticalScroller = YES;
668+
scrollView.hasHorizontalScroller = YES;
669+
scrollView.autohidesScrollers = YES;
670+
}
650671
}
651672
}
652673

@@ -698,6 +719,40 @@ - (void)handleMagnification:(NSMagnificationGestureRecognizer *)recognizer
698719
[scrollView setMagnification:newMagnification centeredAtPoint:centeredPoint];
699720
}
700721

722+
// Handles scroll wheel events for zooming when Command or Option key is held.
723+
// This provides zoom functionality for mice and non-trackpad devices.
724+
- (void)handleScrollWheel:(NSEvent *)event
725+
{
726+
if (!_isZoomEnabled) {
727+
return;
728+
}
729+
730+
// Only zoom if Command or Option key is held
731+
if (!(event.modifierFlags & NSEventModifierFlagCommand) &&
732+
!(event.modifierFlags & NSEventModifierFlagOption)) {
733+
return;
734+
}
735+
736+
NSScrollView *scrollView = (NSScrollView *)_window.contentView;
737+
if (![scrollView isKindOfClass:[NSScrollView class]]) {
738+
return;
739+
}
740+
741+
// Calculate zoom delta (scrolling up = zoom in, down = zoom out)
742+
CGFloat zoomDelta = event.scrollingDeltaY * 0.01; // Scale factor for smooth zooming
743+
CGFloat currentMagnification = scrollView.magnification;
744+
CGFloat newMagnification = currentMagnification + zoomDelta;
745+
746+
// Clamp to min/max magnification
747+
newMagnification = MIN(scrollView.maxMagnification, MAX(scrollView.minMagnification, newMagnification));
748+
749+
// Get mouse location for centered zooming
750+
NSPoint mouseLocation = [_window.contentView convertPoint:event.locationInWindow fromView:nil];
751+
NSPoint centeredPoint = [scrollView.contentView convertPoint:mouseLocation fromView:_window.contentView];
752+
753+
[scrollView setMagnification:newMagnification centeredAtPoint:centeredPoint];
754+
}
755+
701756
// When the mouse approaches the window's edges, this handler adjusts the scroll position
702757
// to provide a smooth panning experience without requiring manual scroll input.
703758
- (void)handleMouseMovement:(NSEvent *)event

0 commit comments

Comments
 (0)