Skip to content

Cocoa/highgui: Incorrectly maps ctrl-click as EVENT_LBUTTONDOWN/EVENT_LBUTTONUP #26661

@NekoAsakura

Description

@NekoAsakura

System Information

OpenCV version: build from https://github.com/opencv/opencv/tree/d9a139f9e85a17b4c47dbca559ed90aef517c279
Operating System / Platform: macOS 15.2
Python version: 3.12

Detailed description

There is a comment left in highgui/src/window_cocoa.mm:

- (void)rightMouseDown:(NSEvent *)theEvent {
// Does not seem to work?
//cout << "rightMouseDown" << endl;
[self cvMouseEvent:theEvent];
}

According to Apple support page, there are two ways to right-click in macOS:

  1. Control-click an item
    Press and hold the Control key while clicking an item using mouse or trackpad.
  2. Control-click items using only mouse/trackpad
    Need to change its settings to open "Secondary click". Details in Apple support page.

After testing, opencv incorrectly maps the first type of right-click as EVENT_LBUTTONDOWN/EVENT_LBUTTONUP.

This is because NSEvent.EventType does not automatically map control-click into a right-click. Developers need to handle this mapping themselves. Similar codes can be found in chromium.

I can submit a pull request to fix it, or update the documentation to give users the option. However, please note that the second type of right-click mentioned above is disabled by default and must be enabled manually in the settings. The mapping of control-click to right-click is likely a common understanding among most macOS users.

Steps to reproduce

import cv2
import numpy as np

EVENTS_MAPPING = {
    cv2.EVENT_LBUTTONDOWN: "Left Button Down",
    cv2.EVENT_LBUTTONUP: "Left Button Up",
    cv2.EVENT_RBUTTONDOWN: "Right Button Down",
    cv2.EVENT_RBUTTONUP: "Right Button Up"
}

def mouse_callback(event, x, y, flags, param):
    global display_text
    event_name = EVENTS_MAPPING.get(event, "")
    if event_name:
        display_text = f"event: {event_name}\nx: {x}\ny: {y}\nflags: {flags}\nparam: {param}"
    else:
        display_text = ""

def main():
    global display_text
    display_text = ""

    width, height = 800, 600
    image = 255 * np.ones((height, width, 3), dtype=np.uint8)

    window_name = "Mouse Event"
    cv2.namedWindow(window_name)

    cv2.setMouseCallback(window_name, mouse_callback)

    while True:
        display_image = image.copy()
        if display_text:
            y0, dy = 30, 30
            for i, line in enumerate(display_text.split('\n')):
                y = y0 + i * dy
                cv2.putText(display_image, line, (12, y), cv2.FONT_HERSHEY_DUPLEX, 1, (0, 0, 0), 1)
        cv2.imshow(window_name, display_image)

        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            break

    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

Issue submission checklist

  • I report the issue, it's not a question
  • I checked the problem with documentation, FAQ, open issues, forum.opencv.org, Stack Overflow, etc and have not found any solution
  • I updated to the latest OpenCV version and the issue is still there
  • There is reproducer code and related data files (videos, images, onnx, etc)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions