Skip to content

Commit 9d22764

Browse files
committed
Merge pull request opencv#19411 from crackwitz:highgui-pollkey
2 parents 2a2e4e7 + 26da491 commit 9d22764

File tree

7 files changed

+152
-72
lines changed

7 files changed

+152
-72
lines changed

modules/highgui/include/opencv2/highgui.hpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -348,23 +348,34 @@ The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\le
348348
milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the
349349
function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is
350350
running on your computer at that time. It returns the code of the pressed key or -1 if no key was
351-
pressed before the specified time had elapsed.
351+
pressed before the specified time had elapsed. To check for a key press but not wait for it, use
352+
#pollKey.
352353
353-
@note
354-
355-
This function is the only method in HighGUI that can fetch and handle events, so it needs to be
356-
called periodically for normal event processing unless HighGUI is used within an environment that
357-
takes care of event processing.
354+
@note The functions #waitKey and #pollKey are the only methods in HighGUI that can fetch and handle
355+
GUI events, so one of them needs to be called periodically for normal event processing unless
356+
HighGUI is used within an environment that takes care of event processing.
358357
359-
@note
360-
361-
The function only works if there is at least one HighGUI window created and the window is active.
362-
If there are several HighGUI windows, any of them can be active.
358+
@note The function only works if there is at least one HighGUI window created and the window is
359+
active. If there are several HighGUI windows, any of them can be active.
363360
364361
@param delay Delay in milliseconds. 0 is the special value that means "forever".
365362
*/
366363
CV_EXPORTS_W int waitKey(int delay = 0);
367364

365+
/** @brief Polls for a pressed key.
366+
367+
The function pollKey polls for a key event without waiting. It returns the code of the pressed key
368+
or -1 if no key was pressed since the last invocation. To wait until a key was pressed, use #waitKey.
369+
370+
@note The functions #waitKey and #pollKey are the only methods in HighGUI that can fetch and handle
371+
GUI events, so one of them needs to be called periodically for normal event processing unless
372+
HighGUI is used within an environment that takes care of event processing.
373+
374+
@note The function only works if there is at least one HighGUI window created and the window is
375+
active. If there are several HighGUI windows, any of them can be active.
376+
*/
377+
CV_EXPORTS_W int pollKey();
378+
368379
/** @brief Displays an image in the specified window.
369380
370381
The function imshow displays an image in the specified window. If the window was created with the
@@ -384,11 +395,12 @@ If the window was not created before this function, it is assumed creating a win
384395
385396
If you need to show an image that is bigger than the screen resolution, you will need to call namedWindow("", WINDOW_NORMAL) before the imshow.
386397
387-
@note This function should be followed by cv::waitKey function which displays the image for specified
388-
milliseconds. Otherwise, it won't display the image. For example, **waitKey(0)** will display the window
389-
infinitely until any keypress (it is suitable for image display). **waitKey(25)** will display a frame
390-
for 25 ms, after which display will be automatically closed. (If you put it in a loop to read
391-
videos, it will display the video frame-by-frame)
398+
@note This function should be followed by a call to cv::waitKey or cv::pollKey to perform GUI
399+
housekeeping tasks that are necessary to actually show the given image and make the window respond
400+
to mouse and keyboard events. Otherwise, it won't display the image and the window might lock up.
401+
For example, **waitKey(0)** will display the window infinitely until any keypress (it is suitable
402+
for image display). **waitKey(25)** will display a frame and wait approximately 25 ms for a key
403+
press (suitable for displaying a video frame-by-frame). To remove the window, use cv::destroyWindow.
392404
393405
@note
394406

modules/highgui/src/window.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ int cv::waitKey(int delay)
297297
return (code != -1) ? (code & 0xff) : -1;
298298
}
299299

300+
// NOTE: cv::pollKey has no C API equivalent. it is implemented in each backend source file.
301+
300302
int cv::createTrackbar(const String& trackbarName, const String& winName,
301303
int* value, int count, TrackbarCallback callback,
302304
void* userdata)

modules/highgui/src/window_QT.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,13 @@ CV_IMPL int cvWaitKey(int delay)
382382
}
383383

384384

385+
int cv::pollKey()
386+
{
387+
CV_TRACE_FUNCTION();
388+
// fallback. please implement a proper polling function
389+
return cvWaitKey(1);
390+
}
391+
385392
//Yannick Verdie
386393
//This function is experimental and some functions (such as cvSet/getWindowProperty will not work)
387394
//We recommend not using this function for now

modules/highgui/src/window_cocoa.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,13 @@ CV_IMPL int cvWaitKey (int maxWait)
632632
return returnCode;
633633
}
634634

635+
int cv::pollKey()
636+
{
637+
CV_TRACE_FUNCTION();
638+
// fallback. please implement a proper polling function
639+
return cvWaitKey(1);
640+
}
641+
635642
CvRect cvGetWindowRect_COCOA( const char* name )
636643
{
637644
CvRect result = cvRect(-1, -1, -1, -1);

modules/highgui/src/window_gtk.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,13 @@ CV_IMPL int cvWaitKey( int delay )
19501950
return last_key;
19511951
}
19521952

1953+
int cv::pollKey()
1954+
{
1955+
CV_TRACE_FUNCTION();
1956+
// fallback. please implement a proper polling function
1957+
return cvWaitKey(1);
1958+
}
1959+
19531960

19541961
#endif // HAVE_GTK
19551962
#endif // _WIN32

modules/highgui/src/window_w32.cpp

Lines changed: 94 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,6 +2064,97 @@ static void showSaveDialog(CvWindow* window)
20642064
}
20652065
}
20662066

2067+
/*
2068+
* message received. check if it belongs to our windows (frame, hwnd).
2069+
* returns true (and value in keyCode) if a key was pressed.
2070+
* otherwise returns false (indication to continue event loop).
2071+
*/
2072+
static bool handleMessage(MSG& message, int& keyCode)
2073+
{
2074+
// whether we have to call translate and dispatch yet
2075+
// otherwise the message was handled specifically
2076+
bool is_processed = false;
2077+
2078+
for (CvWindow* window = hg_windows; window != 0 && is_processed == 0; window = window->next)
2079+
{
2080+
if (!(window->hwnd == message.hwnd || window->frame == message.hwnd))
2081+
continue;
2082+
2083+
is_processed = true;
2084+
switch (message.message)
2085+
{
2086+
case WM_DESTROY:
2087+
case WM_CHAR:
2088+
DispatchMessage(&message);
2089+
keyCode = (int)message.wParam;
2090+
return true;
2091+
2092+
case WM_SYSKEYDOWN:
2093+
if (message.wParam == VK_F10)
2094+
{
2095+
is_processed = true;
2096+
keyCode = (int)(message.wParam << 16);
2097+
return true;
2098+
}
2099+
break;
2100+
2101+
case WM_KEYDOWN:
2102+
TranslateMessage(&message);
2103+
if ((message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
2104+
message.wParam == VK_HOME || message.wParam == VK_END ||
2105+
message.wParam == VK_UP || message.wParam == VK_DOWN ||
2106+
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
2107+
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
2108+
message.wParam == VK_PRIOR || message.wParam == VK_NEXT)
2109+
{
2110+
DispatchMessage(&message);
2111+
is_processed = true;
2112+
keyCode = (int)(message.wParam << 16);
2113+
return true;
2114+
}
2115+
2116+
// Intercept Ctrl+C for copy to clipboard
2117+
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
2118+
::SendMessage(message.hwnd, WM_COPY, 0, 0);
2119+
2120+
// Intercept Ctrl+S for "save as" dialog
2121+
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
2122+
showSaveDialog(window);
2123+
2124+
default:
2125+
DispatchMessage(&message);
2126+
is_processed = true;
2127+
break;
2128+
}
2129+
}
2130+
2131+
if (!is_processed)
2132+
{
2133+
TranslateMessage(&message);
2134+
DispatchMessage(&message);
2135+
}
2136+
2137+
return false; // no value to return, keep processing
2138+
}
2139+
2140+
/*
2141+
* process until queue is empty but don't wait.
2142+
*/
2143+
int cv::pollKey()
2144+
{
2145+
CV_TRACE_FUNCTION();
2146+
for(;;)
2147+
{
2148+
MSG message;
2149+
if (PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE)
2150+
return -1;
2151+
2152+
int keyCode = -1;
2153+
if (handleMessage(message, keyCode))
2154+
return keyCode;
2155+
}
2156+
}
2157+
20672158
CV_IMPL int
20682159
cvWaitKey( int delay )
20692160
{
@@ -2072,9 +2163,7 @@ cvWaitKey( int delay )
20722163

20732164
for(;;)
20742165
{
2075-
CvWindow* window;
20762166
MSG message;
2077-
int is_processed = 0;
20782167

20792168
if( (delay <= 0) && hg_windows)
20802169
GetMessage(&message, 0, 0, 0);
@@ -2087,61 +2176,9 @@ cvWaitKey( int delay )
20872176
continue;
20882177
}
20892178

2090-
for( window = hg_windows; window != 0 && is_processed == 0; window = window->next )
2091-
{
2092-
if( window->hwnd == message.hwnd || window->frame == message.hwnd )
2093-
{
2094-
is_processed = 1;
2095-
switch(message.message)
2096-
{
2097-
case WM_DESTROY:
2098-
case WM_CHAR:
2099-
DispatchMessage(&message);
2100-
return (int)message.wParam;
2101-
2102-
case WM_SYSKEYDOWN:
2103-
if( message.wParam == VK_F10 )
2104-
{
2105-
is_processed = 1;
2106-
return (int)(message.wParam << 16);
2107-
}
2108-
break;
2109-
2110-
case WM_KEYDOWN:
2111-
TranslateMessage(&message);
2112-
if( (message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
2113-
message.wParam == VK_HOME || message.wParam == VK_END ||
2114-
message.wParam == VK_UP || message.wParam == VK_DOWN ||
2115-
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
2116-
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
2117-
message.wParam == VK_PRIOR || message.wParam == VK_NEXT )
2118-
{
2119-
DispatchMessage(&message);
2120-
is_processed = 1;
2121-
return (int)(message.wParam << 16);
2122-
}
2123-
2124-
// Intercept Ctrl+C for copy to clipboard
2125-
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2126-
::SendMessage(message.hwnd, WM_COPY, 0, 0);
2127-
2128-
// Intercept Ctrl+S for "save as" dialog
2129-
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2130-
showSaveDialog(window);
2131-
2132-
default:
2133-
DispatchMessage(&message);
2134-
is_processed = 1;
2135-
break;
2136-
}
2137-
}
2138-
}
2139-
2140-
if( !is_processed )
2141-
{
2142-
TranslateMessage(&message);
2143-
DispatchMessage(&message);
2144-
}
2179+
int keyCode = -1;
2180+
if (handleMessage(message, keyCode))
2181+
return keyCode;
21452182
}
21462183
}
21472184

modules/highgui/src/window_winrt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ CV_IMPL int cvGetTrackbarPos(const char* trackbar_name, const char* window_name)
205205

206206
/********************************** Not YET implemented API ****************************************************/
207207

208+
int cv::pollKey()
209+
{
210+
CV_TRACE_FUNCTION();
211+
CV_WINRT_NO_GUI_ERROR("cvPollKey");
212+
213+
// TODO: implement appropriate logic here
214+
}
215+
208216
CV_IMPL int cvWaitKey(int delay)
209217
{
210218
CV_WINRT_NO_GUI_ERROR("cvWaitKey");

0 commit comments

Comments
 (0)