Skip to content

Commit 26da491

Browse files
committed
implementation of pollKey, companion to waitKey
w32 backend: implemented other backends: stubbed or fallback to waitKey documentation: cross-linked and more precise in some places
1 parent 674ecc5 commit 26da491

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

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

modules/highgui/src/window.cpp

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

284+
// NOTE: cv::pollKey has no C API equivalent. it is implemented in each backend source file.
285+
284286
int cv::createTrackbar(const String& trackbarName, const String& winName,
285287
int* value, int count, TrackbarCallback callback,
286288
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
@@ -1981,6 +1981,97 @@ static void showSaveDialog(CvWindow* window)
19811981
}
19821982
}
19831983

1984+
/*
1985+
* message received. check if it belongs to our windows (frame, hwnd).
1986+
* returns true (and value in keyCode) if a key was pressed.
1987+
* otherwise returns false (indication to continue event loop).
1988+
*/
1989+
static bool handleMessage(MSG& message, int& keyCode)
1990+
{
1991+
// whether we have to call translate and dispatch yet
1992+
// otherwise the message was handled specifically
1993+
bool is_processed = false;
1994+
1995+
for (CvWindow* window = hg_windows; window != 0 && is_processed == 0; window = window->next)
1996+
{
1997+
if (!(window->hwnd == message.hwnd || window->frame == message.hwnd))
1998+
continue;
1999+
2000+
is_processed = true;
2001+
switch (message.message)
2002+
{
2003+
case WM_DESTROY:
2004+
case WM_CHAR:
2005+
DispatchMessage(&message);
2006+
keyCode = (int)message.wParam;
2007+
return true;
2008+
2009+
case WM_SYSKEYDOWN:
2010+
if (message.wParam == VK_F10)
2011+
{
2012+
is_processed = true;
2013+
keyCode = (int)(message.wParam << 16);
2014+
return true;
2015+
}
2016+
break;
2017+
2018+
case WM_KEYDOWN:
2019+
TranslateMessage(&message);
2020+
if ((message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
2021+
message.wParam == VK_HOME || message.wParam == VK_END ||
2022+
message.wParam == VK_UP || message.wParam == VK_DOWN ||
2023+
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
2024+
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
2025+
message.wParam == VK_PRIOR || message.wParam == VK_NEXT)
2026+
{
2027+
DispatchMessage(&message);
2028+
is_processed = true;
2029+
keyCode = (int)(message.wParam << 16);
2030+
return true;
2031+
}
2032+
2033+
// Intercept Ctrl+C for copy to clipboard
2034+
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
2035+
::SendMessage(message.hwnd, WM_COPY, 0, 0);
2036+
2037+
// Intercept Ctrl+S for "save as" dialog
2038+
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
2039+
showSaveDialog(window);
2040+
2041+
default:
2042+
DispatchMessage(&message);
2043+
is_processed = true;
2044+
break;
2045+
}
2046+
}
2047+
2048+
if (!is_processed)
2049+
{
2050+
TranslateMessage(&message);
2051+
DispatchMessage(&message);
2052+
}
2053+
2054+
return false; // no value to return, keep processing
2055+
}
2056+
2057+
/*
2058+
* process until queue is empty but don't wait.
2059+
*/
2060+
int cv::pollKey()
2061+
{
2062+
CV_TRACE_FUNCTION();
2063+
for(;;)
2064+
{
2065+
MSG message;
2066+
if (PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE)
2067+
return -1;
2068+
2069+
int keyCode = -1;
2070+
if (handleMessage(message, keyCode))
2071+
return keyCode;
2072+
}
2073+
}
2074+
19842075
CV_IMPL int
19852076
cvWaitKey( int delay )
19862077
{
@@ -1989,9 +2080,7 @@ cvWaitKey( int delay )
19892080

19902081
for(;;)
19912082
{
1992-
CvWindow* window;
19932083
MSG message;
1994-
int is_processed = 0;
19952084

19962085
if( (delay <= 0) && hg_windows)
19972086
GetMessage(&message, 0, 0, 0);
@@ -2004,61 +2093,9 @@ cvWaitKey( int delay )
20042093
continue;
20052094
}
20062095

2007-
for( window = hg_windows; window != 0 && is_processed == 0; window = window->next )
2008-
{
2009-
if( window->hwnd == message.hwnd || window->frame == message.hwnd )
2010-
{
2011-
is_processed = 1;
2012-
switch(message.message)
2013-
{
2014-
case WM_DESTROY:
2015-
case WM_CHAR:
2016-
DispatchMessage(&message);
2017-
return (int)message.wParam;
2018-
2019-
case WM_SYSKEYDOWN:
2020-
if( message.wParam == VK_F10 )
2021-
{
2022-
is_processed = 1;
2023-
return (int)(message.wParam << 16);
2024-
}
2025-
break;
2026-
2027-
case WM_KEYDOWN:
2028-
TranslateMessage(&message);
2029-
if( (message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
2030-
message.wParam == VK_HOME || message.wParam == VK_END ||
2031-
message.wParam == VK_UP || message.wParam == VK_DOWN ||
2032-
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
2033-
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
2034-
message.wParam == VK_PRIOR || message.wParam == VK_NEXT )
2035-
{
2036-
DispatchMessage(&message);
2037-
is_processed = 1;
2038-
return (int)(message.wParam << 16);
2039-
}
2040-
2041-
// Intercept Ctrl+C for copy to clipboard
2042-
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2043-
::SendMessage(message.hwnd, WM_COPY, 0, 0);
2044-
2045-
// Intercept Ctrl+S for "save as" dialog
2046-
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2047-
showSaveDialog(window);
2048-
2049-
default:
2050-
DispatchMessage(&message);
2051-
is_processed = 1;
2052-
break;
2053-
}
2054-
}
2055-
}
2056-
2057-
if( !is_processed )
2058-
{
2059-
TranslateMessage(&message);
2060-
DispatchMessage(&message);
2061-
}
2096+
int keyCode = -1;
2097+
if (handleMessage(message, keyCode))
2098+
return keyCode;
20622099
}
20632100
}
20642101

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)