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
pull/19411/head
Christoph Rackwitz 4 years ago
parent 674ecc5581
commit 26da491053
  1. 42
      modules/highgui/include/opencv2/highgui.hpp
  2. 2
      modules/highgui/src/window.cpp
  3. 7
      modules/highgui/src/window_QT.cpp
  4. 7
      modules/highgui/src/window_cocoa.mm
  5. 7
      modules/highgui/src/window_gtk.cpp
  6. 151
      modules/highgui/src/window_w32.cpp
  7. 8
      modules/highgui/src/window_winrt.cpp

@ -347,23 +347,34 @@ The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\le
milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the
function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is
running on your computer at that time. It returns the code of the pressed key or -1 if no key was
pressed before the specified time had elapsed.
pressed before the specified time had elapsed. To check for a key press but not wait for it, use
#pollKey.
@note
This function is the only method in HighGUI that can fetch and handle events, so it needs to be
called periodically for normal event processing unless HighGUI is used within an environment that
takes care of event processing.
@note The functions #waitKey and #pollKey are the only methods in HighGUI that can fetch and handle
GUI events, so one of them needs to be called periodically for normal event processing unless
HighGUI is used within an environment that takes care of event processing.
@note
The function only works if there is at least one HighGUI window created and the window is active.
If there are several HighGUI windows, any of them can be active.
@note The function only works if there is at least one HighGUI window created and the window is
active. If there are several HighGUI windows, any of them can be active.
@param delay Delay in milliseconds. 0 is the special value that means "forever".
*/
CV_EXPORTS_W int waitKey(int delay = 0);
/** @brief Polls for a pressed key.
The function pollKey polls for a key event without waiting. It returns the code of the pressed key
or -1 if no key was pressed since the last invocation. To wait until a key was pressed, use #waitKey.
@note The functions #waitKey and #pollKey are the only methods in HighGUI that can fetch and handle
GUI events, so one of them needs to be called periodically for normal event processing unless
HighGUI is used within an environment that takes care of event processing.
@note The function only works if there is at least one HighGUI window created and the window is
active. If there are several HighGUI windows, any of them can be active.
*/
CV_EXPORTS_W int pollKey();
/** @brief Displays an image in the specified window.
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
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.
@note This function should be followed by cv::waitKey function which displays the image for specified
milliseconds. Otherwise, it won't display the image. For example, **waitKey(0)** will display the window
infinitely until any keypress (it is suitable for image display). **waitKey(25)** will display a frame
for 25 ms, after which display will be automatically closed. (If you put it in a loop to read
videos, it will display the video frame-by-frame)
@note This function should be followed by a call to cv::waitKey or cv::pollKey to perform GUI
housekeeping tasks that are necessary to actually show the given image and make the window respond
to mouse and keyboard events. Otherwise, it won't display the image and the window might lock up.
For example, **waitKey(0)** will display the window infinitely until any keypress (it is suitable
for image display). **waitKey(25)** will display a frame and wait approximately 25 ms for a key
press (suitable for displaying a video frame-by-frame). To remove the window, use cv::destroyWindow.
@note

@ -281,6 +281,8 @@ int cv::waitKey(int delay)
return (code != -1) ? (code & 0xff) : -1;
}
// NOTE: cv::pollKey has no C API equivalent. it is implemented in each backend source file.
int cv::createTrackbar(const String& trackbarName, const String& winName,
int* value, int count, TrackbarCallback callback,
void* userdata)

@ -382,6 +382,13 @@ CV_IMPL int cvWaitKey(int delay)
}
int cv::pollKey()
{
CV_TRACE_FUNCTION();
// fallback. please implement a proper polling function
return cvWaitKey(1);
}
//Yannick Verdie
//This function is experimental and some functions (such as cvSet/getWindowProperty will not work)
//We recommend not using this function for now

@ -632,6 +632,13 @@ CV_IMPL int cvWaitKey (int maxWait)
return returnCode;
}
int cv::pollKey()
{
CV_TRACE_FUNCTION();
// fallback. please implement a proper polling function
return cvWaitKey(1);
}
CvRect cvGetWindowRect_COCOA( const char* name )
{
CvRect result = cvRect(-1, -1, -1, -1);

@ -1950,6 +1950,13 @@ CV_IMPL int cvWaitKey( int delay )
return last_key;
}
int cv::pollKey()
{
CV_TRACE_FUNCTION();
// fallback. please implement a proper polling function
return cvWaitKey(1);
}
#endif // HAVE_GTK
#endif // _WIN32

@ -1981,6 +1981,97 @@ static void showSaveDialog(CvWindow* window)
}
}
/*
* message received. check if it belongs to our windows (frame, hwnd).
* returns true (and value in keyCode) if a key was pressed.
* otherwise returns false (indication to continue event loop).
*/
static bool handleMessage(MSG& message, int& keyCode)
{
// whether we have to call translate and dispatch yet
// otherwise the message was handled specifically
bool is_processed = false;
for (CvWindow* window = hg_windows; window != 0 && is_processed == 0; window = window->next)
{
if (!(window->hwnd == message.hwnd || window->frame == message.hwnd))
continue;
is_processed = true;
switch (message.message)
{
case WM_DESTROY:
case WM_CHAR:
DispatchMessage(&message);
keyCode = (int)message.wParam;
return true;
case WM_SYSKEYDOWN:
if (message.wParam == VK_F10)
{
is_processed = true;
keyCode = (int)(message.wParam << 16);
return true;
}
break;
case WM_KEYDOWN:
TranslateMessage(&message);
if ((message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
message.wParam == VK_HOME || message.wParam == VK_END ||
message.wParam == VK_UP || message.wParam == VK_DOWN ||
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
message.wParam == VK_PRIOR || message.wParam == VK_NEXT)
{
DispatchMessage(&message);
is_processed = true;
keyCode = (int)(message.wParam << 16);
return true;
}
// Intercept Ctrl+C for copy to clipboard
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
::SendMessage(message.hwnd, WM_COPY, 0, 0);
// Intercept Ctrl+S for "save as" dialog
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL) >> 15))
showSaveDialog(window);
default:
DispatchMessage(&message);
is_processed = true;
break;
}
}
if (!is_processed)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return false; // no value to return, keep processing
}
/*
* process until queue is empty but don't wait.
*/
int cv::pollKey()
{
CV_TRACE_FUNCTION();
for(;;)
{
MSG message;
if (PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE)
return -1;
int keyCode = -1;
if (handleMessage(message, keyCode))
return keyCode;
}
}
CV_IMPL int
cvWaitKey( int delay )
{
@ -1989,9 +2080,7 @@ cvWaitKey( int delay )
for(;;)
{
CvWindow* window;
MSG message;
int is_processed = 0;
if( (delay <= 0) && hg_windows)
GetMessage(&message, 0, 0, 0);
@ -2004,61 +2093,9 @@ cvWaitKey( int delay )
continue;
}
for( window = hg_windows; window != 0 && is_processed == 0; window = window->next )
{
if( window->hwnd == message.hwnd || window->frame == message.hwnd )
{
is_processed = 1;
switch(message.message)
{
case WM_DESTROY:
case WM_CHAR:
DispatchMessage(&message);
return (int)message.wParam;
case WM_SYSKEYDOWN:
if( message.wParam == VK_F10 )
{
is_processed = 1;
return (int)(message.wParam << 16);
}
break;
case WM_KEYDOWN:
TranslateMessage(&message);
if( (message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
message.wParam == VK_HOME || message.wParam == VK_END ||
message.wParam == VK_UP || message.wParam == VK_DOWN ||
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
message.wParam == VK_PRIOR || message.wParam == VK_NEXT )
{
DispatchMessage(&message);
is_processed = 1;
return (int)(message.wParam << 16);
}
// Intercept Ctrl+C for copy to clipboard
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
::SendMessage(message.hwnd, WM_COPY, 0, 0);
// Intercept Ctrl+S for "save as" dialog
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
showSaveDialog(window);
default:
DispatchMessage(&message);
is_processed = 1;
break;
}
}
}
if( !is_processed )
{
TranslateMessage(&message);
DispatchMessage(&message);
}
int keyCode = -1;
if (handleMessage(message, keyCode))
return keyCode;
}
}

@ -205,6 +205,14 @@ CV_IMPL int cvGetTrackbarPos(const char* trackbar_name, const char* window_name)
/********************************** Not YET implemented API ****************************************************/
int cv::pollKey()
{
CV_TRACE_FUNCTION();
CV_WINRT_NO_GUI_ERROR("cvPollKey");
// TODO: implement appropriate logic here
}
CV_IMPL int cvWaitKey(int delay)
{
CV_WINRT_NO_GUI_ERROR("cvWaitKey");

Loading…
Cancel
Save