Made wxContextHelp implementation generic and added wxFindWindowAtPointer,

wxGetMousePosition functions


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8280 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart 2000-09-07 09:43:05 +00:00
parent bfabd11afb
commit 3723b7b1d8
9 changed files with 261 additions and 261 deletions

View File

@ -93,25 +93,15 @@ public:
bool BeginContextHelp(wxWindow* win); bool BeginContextHelp(wxWindow* win);
bool EndContextHelp(); bool EndContextHelp();
bool EventLoop(const wxCursor& cursor, wxWindow* win); bool EventLoop();
bool DispatchEvent(wxWindow* win, const wxPoint& pt); bool DispatchEvent(wxWindow* win, const wxPoint& pt);
#ifdef __WXMSW__ void SetStatus(bool status) { m_status = status; }
bool ProcessHelpMessage(WXMSG* wxmsg, const wxCursor& cursor, wxWindow* win);
#endif
#ifdef __WXGTK__
void SetStatus(bool status, const wxPoint& pt) { m_status = status; m_mousePos = pt; }
#endif
protected: protected:
bool m_inHelp; bool m_inHelp;
bool m_status; // TRUE if the user left-clicked
#ifdef __WXGTK__
bool m_status; // The user left-clicked
wxPoint m_mousePos;
#endif
}; };
#endif // wxUSE_HELP #endif // wxUSE_HELP

View File

@ -885,11 +885,18 @@ inline wxWindow *wxWindowBase::GetGrandParent() const
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// global function // global functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
WXDLLEXPORT extern wxWindow* wxGetActiveWindow(); WXDLLEXPORT extern wxWindow* wxGetActiveWindow();
// Find the wxWindow at the current mouse position, also returning the mouse
// position.
WXDLLEXPORT extern wxWindow* wxFindWindowAtPointer(wxPoint& pt);
// Get the current mouse position.
WXDLLEXPORT extern wxPoint wxGetMousePosition();
// deprecated (doesn't start with 'wx' prefix), use wxWindow::NewControlId() // deprecated (doesn't start with 'wx' prefix), use wxWindow::NewControlId()
inline WXDLLEXPORT int NewControlId() { return wxWindowBase::NewControlId(); } inline WXDLLEXPORT int NewControlId() { return wxWindowBase::NewControlId(); }

View File

@ -27,17 +27,6 @@
#include "wx/helpbase.h" #include "wx/helpbase.h"
#include "wx/app.h" #include "wx/app.h"
#ifdef __WXMSW__
#include "wx/msw/private.h"
#endif
#ifdef __WXGTK__
#include <gtk/gtk.h>
#include <gtk/gtkprivate.h>
#include "wx/gtk/win_gtk.h"
#include "wx/msgdlg.h"
#endif
#if wxUSE_HELP #if wxUSE_HELP
IMPLEMENT_CLASS(wxHelpControllerBase, wxObject) IMPLEMENT_CLASS(wxHelpControllerBase, wxObject)
@ -46,9 +35,8 @@ IMPLEMENT_CLASS(wxHelpControllerBase, wxObject)
* Invokes context-sensitive help * Invokes context-sensitive help
*/ */
#ifdef __WXGTK__ // This class exists in order to eat events until the left mouse
// This class exists in order to eat events until the left mouse // button is pressed
// button is pressed
class wxContextHelpEvtHandler: public wxEvtHandler class wxContextHelpEvtHandler: public wxEvtHandler
{ {
public: public:
@ -62,7 +50,6 @@ public:
//// Data //// Data
wxContextHelp* m_contextHelp; wxContextHelp* m_contextHelp;
}; };
#endif
IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject)
@ -80,123 +67,38 @@ wxContextHelp::~wxContextHelp()
EndContextHelp(); EndContextHelp();
} }
#ifdef __WXGTK__ // Begin 'context help mode'
wxWindow* wxFindWindowForGdkWindow(wxWindow* win, GdkWindow* gdkWindow)
{
GdkWindow* thisGdkWindow1 = 0;
GdkWindow* thisGdkWindow2 = 0;
if (win->m_wxwindow)
thisGdkWindow1 = GTK_PIZZA(win->m_wxwindow)->bin_window;
thisGdkWindow2 = win->m_widget->window;
if (gdkWindow == thisGdkWindow1 || gdkWindow == thisGdkWindow2)
return win;
wxNode* node = win->GetChildren().First();
while (node)
{
wxWindow* child = (wxWindow*) node->Data();
wxWindow* found = wxFindWindowForGdkWindow(child, gdkWindow);
if (found)
return found;
node = node->Next();
}
return NULL;
}
#endif
bool wxContextHelp::BeginContextHelp(wxWindow* win) bool wxContextHelp::BeginContextHelp(wxWindow* win)
{ {
if (!win) if (!win)
win = wxTheApp->GetTopWindow(); win = wxTheApp->GetTopWindow();
if (!win) if (!win)
return FALSE; return FALSE;
#ifdef __WXMSW__
wxCursor cursor(wxCURSOR_QUESTION_ARROW); wxCursor cursor(wxCURSOR_QUESTION_ARROW);
wxCursor oldCursor = win->GetCursor();
win->SetCursor(cursor);
wxSetCursor(cursor); wxSetCursor(cursor);
win->CaptureMouse();
EventLoop(cursor, win);
win->ReleaseMouse();
#endif
#ifdef __WXGTK__
m_status = FALSE;
GdkCursor* query_cursor = gdk_cursor_new (GDK_QUESTION_ARROW);
GdkWindow* gdkWindow = 0;
GtkWidget* gtkWidget = 0;
if (win->m_wxwindow)
{
gtkWidget = win->m_wxwindow;
gdkWindow = GTK_PIZZA(win->m_wxwindow)->bin_window;
}
else
{
gtkWidget = win->m_widget;
gdkWindow = win->m_widget->window;
}
gint failure = gdk_pointer_grab (gdkWindow,
FALSE,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK,
NULL,
query_cursor,
GDK_CURRENT_TIME);
if (failure)
{
gdk_cursor_destroy (query_cursor);
query_cursor = NULL;
}
gdk_keyboard_grab (gdkWindow, FALSE, GDK_CURRENT_TIME);
gtk_grab_add (gtkWidget);
win->PushEventHandler(new wxContextHelpEvtHandler(this)); win->PushEventHandler(new wxContextHelpEvtHandler(this));
// wxLogDebug("Entering loop."); win->CaptureMouse();
EventLoop(wxNullCursor, win); EventLoop();
// wxLogDebug("Exiting loop."); win->ReleaseMouse();
win->PopEventHandler(TRUE); win->PopEventHandler(TRUE);
gtk_grab_remove (gtkWidget); win->SetCursor(oldCursor);
gdk_keyboard_ungrab (GDK_CURRENT_TIME);
if (query_cursor)
{
gdk_pointer_ungrab (GDK_CURRENT_TIME);
gdk_cursor_destroy (query_cursor);
query_cursor = NULL;
}
if (m_status) if (m_status)
{ {
//wxMessageBox("Left-clicked"); wxPoint pt;
//wxPoint screenPt = win->ClientToScreen(m_mousePos); wxWindow* winAtPtr = wxFindWindowAtPointer(pt);
int x, y; if (winAtPtr)
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y); DispatchEvent(winAtPtr, pt);
if (windowAtPtr) }
{
wxWindow* wxWinAtPtr = wxFindWindowForGdkWindow(win, windowAtPtr);
if (wxWinAtPtr)
{
DispatchEvent(wxWinAtPtr, wxPoint(x, y));
}
}
}
else
{
//wxMessageBox("Cancelled");
}
#endif
return TRUE; return TRUE;
} }
@ -208,27 +110,8 @@ bool wxContextHelp::EndContextHelp()
return TRUE; return TRUE;
} }
bool wxContextHelp::EventLoop(const wxCursor& cursor, wxWindow* win) bool wxContextHelp::EventLoop()
{ {
#ifdef __WXMSW__
m_inHelp = TRUE;
while ( m_inHelp )
{
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!ProcessHelpMessage((WXMSG*) & msg, cursor, win))
{
m_inHelp = FALSE;
}
}
else
{
wxTheApp->ProcessIdle();
}
}
return TRUE;
#elif defined(__WXGTK__)
m_inHelp = TRUE; m_inHelp = TRUE;
while ( m_inHelp ) while ( m_inHelp )
{ {
@ -242,131 +125,41 @@ bool wxContextHelp::EventLoop(const wxCursor& cursor, wxWindow* win)
} }
} }
return TRUE; return TRUE;
#else
return FALSE;
#endif
} }
// PROBLEM: If you click on the panel or other descendant of the
// given window, then it doesn't go to this handler, even though
// there's a grab.
bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event) bool wxContextHelpEvtHandler::ProcessEvent(wxEvent& event)
{ {
//wxLogDebug("Got event"); switch (event.GetEventType())
if (event.GetEventType() == wxEVT_LEFT_DOWN)
{ {
//wxLogDebug("Mouse event"); case wxEVT_LEFT_DOWN:
wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
m_contextHelp->SetStatus(TRUE, mouseEvent.GetPosition());
m_contextHelp->EndContextHelp();
}
// Don't know why these aren't being caught
else if (event.GetEventType() == wxEVT_CHAR || event.GetEventType() == wxEVT_KEY_DOWN)
{
//wxKeyEvent& keyEvent = (wxKeyEvent&) event;
if (TRUE) // keyEvent.GetKeyCode() == WXK_ESCAPE)
{ {
m_contextHelp->SetStatus(FALSE, wxPoint(0, 0)); wxMouseEvent& mouseEvent = (wxMouseEvent&) event;
m_contextHelp->SetStatus(TRUE);
m_contextHelp->EndContextHelp(); m_contextHelp->EndContextHelp();
}
}
return TRUE;
}
#ifdef __WXMSW__
bool wxContextHelp::ProcessHelpMessage(WXMSG* wxmsg, const wxCursor& cursor, wxWindow* winInQuestion)
{
MSG& msg = * (MSG*) wxmsg;
if (msg.message == WM_KEYDOWN || msg.wParam == VK_ESCAPE)
{
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
return FALSE;
}
if (msg.message == WM_CAPTURECHANGED)
{
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
return FALSE;
}
if (msg.message == WM_ACTIVATE)
{
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
return FALSE;
}
if ((msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST))
// || (msg.message >= WM_NCMOUSEFIRST && msg.message <= WM_NCMOUSELAST))
{
wxSetCursor(cursor);
HWND hWndHit = ::WindowFromPoint(msg.pt);
wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ;
HWND hWnd = hWndHit;
// Try to find a window with a wxWindow associated with it
while (!win && (hWnd != 0))
{
hWnd = ::GetParent(hWnd);
win = wxFindWinFromHandle((WXHWND) hWnd) ;
}
if (win)
{
// It's a wxWindows window
if (msg.message != WM_LBUTTONDOWN)
{
// Hit one of our owned windows -- eat the message.
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
return TRUE;
}
int iHit = (int)::SendMessage(hWndHit, WM_NCHITTEST, 0,
MAKELONG(msg.pt.x, msg.pt.y));
if (iHit == HTMENU || iHit == HTSYSMENU)
{
// Eat this message, send the event and return
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
DispatchEvent(win, wxPoint(msg.pt.x, msg.pt.y));
return FALSE;
}
else if (iHit == HTCLIENT)
{
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
DispatchEvent(win, wxPoint(msg.pt.x, msg.pt.y));
return FALSE;
}
else
{
PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE);
return FALSE;
}
}
else
{
// Someone else's message
if (PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return TRUE; return TRUE;
break;
}
case wxEVT_CHAR:
case wxEVT_KEY_DOWN:
case wxEVT_ACTIVATE:
case wxEVT_MOUSE_CAPTURE_CHANGED:
{
m_contextHelp->SetStatus(FALSE);
m_contextHelp->EndContextHelp();
return TRUE;
break;
}
case wxEVT_PAINT:
case wxEVT_ERASE_BACKGROUND:
{
event.Skip();
return FALSE;
break;
} }
} }
else
{
// allow all other messages to go through (capture still set)
if (PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE))
DispatchMessage(&msg);
return TRUE;
}
return TRUE; return TRUE;
} }
#endif
// Dispatch the help event to the relevant window // Dispatch the help event to the relevant window
bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt) bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
@ -387,5 +180,4 @@ bool wxContextHelp::DispatchEvent(wxWindow* win, const wxPoint& pt)
return eventProcessed; return eventProcessed;
} }
#endif // wxUSE_HELP #endif // wxUSE_HELP

View File

@ -3753,3 +3753,62 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
} }
*/ */
} }
// Helper for wxFindWindowAtPointer
wxWindow* wxFindWindowForGdkWindow(wxWindow* win, GdkWindow* gdkWindow)
{
GdkWindow* thisGdkWindow1 = 0;
GdkWindow* thisGdkWindow2 = 0;
if (win->m_wxwindow)
thisGdkWindow1 = GTK_PIZZA(win->m_wxwindow)->bin_window;
thisGdkWindow2 = win->m_widget->window;
if (gdkWindow == thisGdkWindow1 || gdkWindow == thisGdkWindow2)
return win;
wxNode* node = win->GetChildren().First();
while (node)
{
wxWindow* child = (wxWindow*) node->Data();
wxWindow* found = wxFindWindowForGdkWindow(child, gdkWindow);
if (found)
return found;
node = node->Next();
}
return NULL;
}
// Find the wxWindow at the current mouse position, also returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
int x, y;
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
pt.x = x;
pt.y = y;
if (windowAtPtr)
{
wxNode* node = wxTopLevelWindows.First();
while (node)
{
wxWindow* win = (wxWindow*) node->Data();
wxWindow* wxWinAtPtr = wxFindWindowForGdkWindow(win, windowAtPtr);
if (wxWinAtPtr)
return wxWinAtPtr;
node = node->Next();
}
}
return NULL;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
int x, y;
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
return wxPoint(x, y);
}

View File

@ -3753,3 +3753,62 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
} }
*/ */
} }
// Helper for wxFindWindowAtPointer
wxWindow* wxFindWindowForGdkWindow(wxWindow* win, GdkWindow* gdkWindow)
{
GdkWindow* thisGdkWindow1 = 0;
GdkWindow* thisGdkWindow2 = 0;
if (win->m_wxwindow)
thisGdkWindow1 = GTK_PIZZA(win->m_wxwindow)->bin_window;
thisGdkWindow2 = win->m_widget->window;
if (gdkWindow == thisGdkWindow1 || gdkWindow == thisGdkWindow2)
return win;
wxNode* node = win->GetChildren().First();
while (node)
{
wxWindow* child = (wxWindow*) node->Data();
wxWindow* found = wxFindWindowForGdkWindow(child, gdkWindow);
if (found)
return found;
node = node->Next();
}
return NULL;
}
// Find the wxWindow at the current mouse position, also returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
int x, y;
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
pt.x = x;
pt.y = y;
if (windowAtPtr)
{
wxNode* node = wxTopLevelWindows.First();
while (node)
{
wxWindow* win = (wxWindow*) node->Data();
wxWindow* wxWinAtPtr = wxFindWindowForGdkWindow(win, windowAtPtr);
if (wxWinAtPtr)
return wxWinAtPtr;
node = node->Next();
}
}
return NULL;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
int x, y;
GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
return wxPoint(x, y);
}

View File

@ -2356,3 +2356,19 @@ wxMacDrawingClientHelper::~wxMacDrawingClientHelper()
if ( m_formerPort != m_currentPort ) if ( m_formerPort != m_currentPort )
SetPort( m_formerPort ) ; SetPort( m_formerPort ) ;
} }
// Find the wxWindow at the current mouse position, returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
wxFAIL_MSG(_("Not implemented"));
return NULL;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
wxFAIL_MSG(_("Not implemented"));
return wxPoint;
}

View File

@ -2356,3 +2356,19 @@ wxMacDrawingClientHelper::~wxMacDrawingClientHelper()
if ( m_formerPort != m_currentPort ) if ( m_formerPort != m_currentPort )
SetPort( m_formerPort ) ; SetPort( m_formerPort ) ;
} }
// Find the wxWindow at the current mouse position, returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
wxFAIL_MSG(_("Not implemented"));
return NULL;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
wxFAIL_MSG(_("Not implemented"));
return wxPoint;
}

View File

@ -2984,9 +2984,25 @@ void wxWindow::ChangeFont(bool keepOriginalSize)
wxWindow *wxGetActiveWindow() wxWindow *wxGetActiveWindow()
{ {
// TODO // TODO
wxFAIL_MSG(_("Not implemented"));
return NULL; return NULL;
} }
// Find the wxWindow at the current mouse position, returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
wxFAIL_MSG(_("Not implemented"));
return NULL;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
wxFAIL_MSG(_("Not implemented"));
return wxPoint;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxNoOptimize: switch off size optimization // wxNoOptimize: switch off size optimization
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -2390,6 +2390,23 @@ bool wxWindow::MSWCreate(int id,
::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0, ::SetWindowPos(GetHwnd(), NULL, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
} }
#if defined(__WIN95__)
// For some reason, the system menu is activated when we use the
// WS_EX_CONTEXTHELP style, so let's set a reasonable icon
if (extendedStyle & WS_EX_CONTEXTHELP)
{
if (wxTheApp->GetTopWindow() && (wxTheApp->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame))))
{
wxIcon icon = ((wxFrame*)wxTheApp->GetTopWindow())->GetIcon();
if (icon.Ok())
SendMessage(GetHwnd(), WM_SETICON,
(WPARAM)TRUE, (LPARAM)(HICON) icon.GetHICON());
}
}
#endif // __WIN95__
// JACS: is the following still necessary? The above seems to work.
// ::SetWindowLong(GWL_EXSTYLE) doesn't work for the dialogs, so try // ::SetWindowLong(GWL_EXSTYLE) doesn't work for the dialogs, so try
// to take care of (at least some) extended style flags ourselves // to take care of (at least some) extended style flags ourselves
@ -4367,3 +4384,31 @@ static TEXTMETRIC wxGetTextMetrics(const wxWindow *win)
return tm; return tm;
} }
// Find the wxWindow at the current mouse position, returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)
{
// Use current message to find last mouse position
extern MSG s_currentMsg;
HWND hWndHit = ::WindowFromPoint(s_currentMsg.pt);
wxWindow* win = wxFindWinFromHandle((WXHWND) hWndHit) ;
HWND hWnd = hWndHit;
// Try to find a window with a wxWindow associated with it
while (!win && (hWnd != 0))
{
hWnd = ::GetParent(hWnd);
win = wxFindWinFromHandle((WXHWND) hWnd) ;
}
return win;
}
// Get the current mouse position.
wxPoint wxGetMousePosition()
{
extern MSG s_currentMsg;
return wxPoint(s_currentMsg.pt.x, s_currentMsg.pt.y);
}