From 68237521ed730777d792f8f3ca90cda38fa5acaa Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Wed, 6 Sep 2000 16:44:17 +0000 Subject: [PATCH] Implemented wxHelpContext for wxGTK. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8276 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/helpbase.h | 9 +++ src/common/helpbase.cpp | 171 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/include/wx/helpbase.h b/include/wx/helpbase.h index 97e42f6e9a..5cfe17c0b2 100644 --- a/include/wx/helpbase.h +++ b/include/wx/helpbase.h @@ -100,9 +100,18 @@ public: 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: bool m_inHelp; + +#ifdef __WXGTK__ + bool m_status; // The user left-clicked + wxPoint m_mousePos; +#endif }; #endif // wxUSE_HELP diff --git a/src/common/helpbase.cpp b/src/common/helpbase.cpp index 1468954b39..d07256a257 100644 --- a/src/common/helpbase.cpp +++ b/src/common/helpbase.cpp @@ -31,6 +31,13 @@ #include "wx/msw/private.h" #endif +#ifdef __WXGTK__ +#include +#include +#include "wx/gtk/win_gtk.h" +#include "wx/msgdlg.h" +#endif + #if wxUSE_HELP IMPLEMENT_CLASS(wxHelpControllerBase, wxObject) @@ -39,6 +46,24 @@ IMPLEMENT_CLASS(wxHelpControllerBase, wxObject) * Invokes context-sensitive help */ +#ifdef __WXGTK__ + // This class exists in order to eat events until the left mouse + // button is pressed +class wxContextHelpEvtHandler: public wxEvtHandler +{ +public: + wxContextHelpEvtHandler(wxContextHelp* contextHelp) + { + m_contextHelp = contextHelp; + } + + virtual bool ProcessEvent(wxEvent& event); + +//// Data + wxContextHelp* m_contextHelp; +}; +#endif + IMPLEMENT_DYNAMIC_CLASS(wxContextHelp, wxObject) wxContextHelp::wxContextHelp(wxWindow* win, bool beginHelp) @@ -55,13 +80,41 @@ wxContextHelp::~wxContextHelp() EndContextHelp(); } +#ifdef __WXGTK__ +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) { if (!win) win = wxTheApp->GetTopWindow(); if (!win) return FALSE; - +#ifdef __WXMSW__ wxCursor cursor(wxCURSOR_QUESTION_ARROW); wxSetCursor(cursor); @@ -70,6 +123,80 @@ bool wxContextHelp::BeginContextHelp(wxWindow* win) 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)); + + // wxLogDebug("Entering loop."); + + EventLoop(wxNullCursor, win); + + // wxLogDebug("Exiting loop."); + + win->PopEventHandler(TRUE); + + gtk_grab_remove (gtkWidget); + 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) + { + //wxMessageBox("Left-clicked"); + //wxPoint screenPt = win->ClientToScreen(m_mousePos); + int x, y; + GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y); + if (windowAtPtr) + { + wxWindow* wxWinAtPtr = wxFindWindowForGdkWindow(win, windowAtPtr); + if (wxWinAtPtr) + { + DispatchEvent(wxWinAtPtr, wxPoint(x, y)); + } + } + } + else + { + //wxMessageBox("Cancelled"); + } +#endif return TRUE; } @@ -101,11 +228,53 @@ bool wxContextHelp::EventLoop(const wxCursor& cursor, wxWindow* win) } } return TRUE; +#elif defined(__WXGTK__) + m_inHelp = TRUE; + while ( m_inHelp ) + { + if (wxTheApp->Pending()) + { + wxTheApp->Dispatch(); + } + else + { + wxTheApp->ProcessIdle(); + } + } + 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) +{ + //wxLogDebug("Got event"); + + if (event.GetEventType() == wxEVT_LEFT_DOWN) + { + //wxLogDebug("Mouse event"); + 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)); + m_contextHelp->EndContextHelp(); + } + } + + return TRUE; +} + #ifdef __WXMSW__ bool wxContextHelp::ProcessHelpMessage(WXMSG* wxmsg, const wxCursor& cursor, wxWindow* winInQuestion) { -- 2.45.2