@@ -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