]>
git.saurik.com Git - wxWidgets.git/blob - src/common/helpbase.cpp
d07256a2572ee353ff3b8e23dd0f966b5dfa9640
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Help system base classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "helpbase.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/helpbase.h"
31 #include "wx/msw/private.h"
36 #include <gtk/gtkprivate.h>
37 #include "wx/gtk/win_gtk.h"
38 #include "wx/msgdlg.h"
43 IMPLEMENT_CLASS(wxHelpControllerBase
, wxObject
)
46 * Invokes context-sensitive help
50 // This class exists in order to eat events until the left mouse
52 class wxContextHelpEvtHandler
: public wxEvtHandler
55 wxContextHelpEvtHandler(wxContextHelp
* contextHelp
)
57 m_contextHelp
= contextHelp
;
60 virtual bool ProcessEvent(wxEvent
& event
);
63 wxContextHelp
* m_contextHelp
;
67 IMPLEMENT_DYNAMIC_CLASS(wxContextHelp
, wxObject
)
69 wxContextHelp::wxContextHelp(wxWindow
* win
, bool beginHelp
)
74 BeginContextHelp(win
);
77 wxContextHelp::~wxContextHelp()
84 wxWindow
* wxFindWindowForGdkWindow(wxWindow
* win
, GdkWindow
* gdkWindow
)
86 GdkWindow
* thisGdkWindow1
= 0;
87 GdkWindow
* thisGdkWindow2
= 0;
90 thisGdkWindow1
= GTK_PIZZA(win
->m_wxwindow
)->bin_window
;
92 thisGdkWindow2
= win
->m_widget
->window
;
94 if (gdkWindow
== thisGdkWindow1
|| gdkWindow
== thisGdkWindow2
)
97 wxNode
* node
= win
->GetChildren().First();
100 wxWindow
* child
= (wxWindow
*) node
->Data();
101 wxWindow
* found
= wxFindWindowForGdkWindow(child
, gdkWindow
);
111 bool wxContextHelp::BeginContextHelp(wxWindow
* win
)
114 win
= wxTheApp
->GetTopWindow();
118 wxCursor
cursor(wxCURSOR_QUESTION_ARROW
);
123 EventLoop(cursor
, win
);
130 GdkCursor
* query_cursor
= gdk_cursor_new (GDK_QUESTION_ARROW
);
132 GdkWindow
* gdkWindow
= 0;
133 GtkWidget
* gtkWidget
= 0;
137 gtkWidget
= win
->m_wxwindow
;
138 gdkWindow
= GTK_PIZZA(win
->m_wxwindow
)->bin_window
;
142 gtkWidget
= win
->m_widget
;
143 gdkWindow
= win
->m_widget
->window
;
146 gint failure
= gdk_pointer_grab (gdkWindow
,
148 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
|
149 GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK
,
155 gdk_cursor_destroy (query_cursor
);
158 gdk_keyboard_grab (gdkWindow
, FALSE
, GDK_CURRENT_TIME
);
159 gtk_grab_add (gtkWidget
);
161 win
->PushEventHandler(new wxContextHelpEvtHandler(this));
163 // wxLogDebug("Entering loop.");
165 EventLoop(wxNullCursor
, win
);
167 // wxLogDebug("Exiting loop.");
169 win
->PopEventHandler(TRUE
);
171 gtk_grab_remove (gtkWidget
);
172 gdk_keyboard_ungrab (GDK_CURRENT_TIME
);
175 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
176 gdk_cursor_destroy (query_cursor
);
182 //wxMessageBox("Left-clicked");
183 //wxPoint screenPt = win->ClientToScreen(m_mousePos);
185 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
188 wxWindow
* wxWinAtPtr
= wxFindWindowForGdkWindow(win
, windowAtPtr
);
191 DispatchEvent(wxWinAtPtr
, wxPoint(x
, y
));
197 //wxMessageBox("Cancelled");
204 bool wxContextHelp::EndContextHelp()
211 bool wxContextHelp::EventLoop(const wxCursor
& cursor
, wxWindow
* win
)
218 if (::PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
))
220 if (!ProcessHelpMessage((WXMSG
*) & msg
, cursor
, win
))
227 wxTheApp
->ProcessIdle();
231 #elif defined(__WXGTK__)
235 if (wxTheApp
->Pending())
237 wxTheApp
->Dispatch();
241 wxTheApp
->ProcessIdle();
250 // PROBLEM: If you click on the panel or other descendant of the
251 // given window, then it doesn't go to this handler, even though
253 bool wxContextHelpEvtHandler::ProcessEvent(wxEvent
& event
)
255 //wxLogDebug("Got event");
257 if (event
.GetEventType() == wxEVT_LEFT_DOWN
)
259 //wxLogDebug("Mouse event");
260 wxMouseEvent
& mouseEvent
= (wxMouseEvent
&) event
;
261 m_contextHelp
->SetStatus(TRUE
, mouseEvent
.GetPosition());
262 m_contextHelp
->EndContextHelp();
264 // Don't know why these aren't being caught
265 else if (event
.GetEventType() == wxEVT_CHAR
|| event
.GetEventType() == wxEVT_KEY_DOWN
)
267 //wxKeyEvent& keyEvent = (wxKeyEvent&) event;
268 if (TRUE
) // keyEvent.GetKeyCode() == WXK_ESCAPE)
270 m_contextHelp
->SetStatus(FALSE
, wxPoint(0, 0));
271 m_contextHelp
->EndContextHelp();
279 bool wxContextHelp::ProcessHelpMessage(WXMSG
* wxmsg
, const wxCursor
& cursor
, wxWindow
* winInQuestion
)
281 MSG
& msg
= * (MSG
*) wxmsg
;
283 if (msg
.message
== WM_KEYDOWN
|| msg
.wParam
== VK_ESCAPE
)
285 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
289 if (msg
.message
== WM_CAPTURECHANGED
)
291 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
295 if (msg
.message
== WM_ACTIVATE
)
297 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
301 if ((msg
.message
>= WM_MOUSEFIRST
&& msg
.message
<= WM_MOUSELAST
))
302 // || (msg.message >= WM_NCMOUSEFIRST && msg.message <= WM_NCMOUSELAST))
306 HWND hWndHit
= ::WindowFromPoint(msg
.pt
);
308 wxWindow
* win
= wxFindWinFromHandle((WXHWND
) hWndHit
) ;
311 // Try to find a window with a wxWindow associated with it
312 while (!win
&& (hWnd
!= 0))
314 hWnd
= ::GetParent(hWnd
);
315 win
= wxFindWinFromHandle((WXHWND
) hWnd
) ;
320 // It's a wxWindows window
321 if (msg
.message
!= WM_LBUTTONDOWN
)
323 // Hit one of our owned windows -- eat the message.
324 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
327 int iHit
= (int)::SendMessage(hWndHit
, WM_NCHITTEST
, 0,
328 MAKELONG(msg
.pt
.x
, msg
.pt
.y
));
329 if (iHit
== HTMENU
|| iHit
== HTSYSMENU
)
331 // Eat this message, send the event and return
332 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
333 DispatchEvent(win
, wxPoint(msg
.pt
.x
, msg
.pt
.y
));
336 else if (iHit
== HTCLIENT
)
338 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
339 DispatchEvent(win
, wxPoint(msg
.pt
.x
, msg
.pt
.y
));
344 PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
);
350 // Someone else's message
351 if (PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
))
353 ::TranslateMessage(&msg
);
354 ::DispatchMessage(&msg
);
361 // allow all other messages to go through (capture still set)
362 if (PeekMessage(&msg
, NULL
, msg
.message
, msg
.message
, PM_REMOVE
))
363 DispatchMessage(&msg
);
371 // Dispatch the help event to the relevant window
372 bool wxContextHelp::DispatchEvent(wxWindow
* win
, const wxPoint
& pt
)
374 wxWindow
* subjectOfHelp
= win
;
375 bool eventProcessed
= FALSE
;
376 while (subjectOfHelp
&& !eventProcessed
)
378 wxHelpEvent
helpEvent(wxEVT_HELP
, subjectOfHelp
->GetId(), pt
) ;
379 helpEvent
.SetEventObject(this);
380 eventProcessed
= win
->GetEventHandler()->ProcessEvent(helpEvent
);
382 // Go up the window hierarchy until the event is handled (or not).
383 // I.e. keep submitting ancestor windows until one is recognised
384 // by the app code that processes the ids and displays help.
385 subjectOfHelp
= subjectOfHelp
->GetParent();
387 return eventProcessed
;