]> git.saurik.com Git - wxWidgets.git/blame - src/common/event.cpp
added wxTextEntry::AutoComplete() and implemented it for wxGTK
[wxWidgets.git] / src / common / event.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
c54de5ae 2// Name: src/common/event.cpp
c801d85f
KB
3// Purpose: Event classes
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
8e193f38
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
0b746ba8 24 #pragma hdrstop
c801d85f
KB
25#endif
26
d5da0ce7
WS
27#include "wx/event.h"
28
c801d85f 29#ifndef WX_PRECOMP
e90c1d2a 30 #include "wx/list.h"
8ecff181 31 #include "wx/app.h"
de6185e2 32 #include "wx/utils.h"
bb90a3e6 33 #include "wx/stopwatch.h"
02761f6c 34 #include "wx/module.h"
e90c1d2a
VZ
35
36 #if wxUSE_GUI
a8ff046b 37 #include "wx/window.h"
e90c1d2a 38 #include "wx/control.h"
e90c1d2a 39 #include "wx/dc.h"
75a29298 40 #include "wx/textctrl.h"
264cb7f5 41 #include "wx/validate.h"
e90c1d2a 42 #endif // wxUSE_GUI
c801d85f
KB
43#endif
44
8e193f38
VZ
45// ----------------------------------------------------------------------------
46// wxWin macros
47// ----------------------------------------------------------------------------
48
3ed2104c
VZ
49#if wxUSE_BASE
50 IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
51 IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
b46b1d59 52 IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent, wxEvent)
3ed2104c 53#endif // wxUSE_BASE
e90c1d2a 54
23f681ec
VZ
55#if wxUSE_GUI
56 IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
57 IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent, wxCommandEvent)
58 IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
59 IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent, wxEvent)
60 IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent, wxEvent)
61 IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent, wxEvent)
62 IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent, wxEvent)
63 IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent, wxEvent)
1e6feb95 64 IMPLEMENT_DYNAMIC_CLASS(wxNcPaintEvent, wxEvent)
23f681ec
VZ
65 IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent, wxEvent)
66 IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent, wxEvent)
67 IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent, wxEvent)
456bc6d9 68 IMPLEMENT_DYNAMIC_CLASS(wxChildFocusEvent, wxCommandEvent)
23f681ec
VZ
69 IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent, wxEvent)
70 IMPLEMENT_DYNAMIC_CLASS(wxShowEvent, wxEvent)
71 IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent, wxEvent)
72 IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent, wxEvent)
73 IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent, wxEvent)
74 IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent, wxEvent)
75 IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent, wxEvent)
76 IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent, wxEvent)
77 IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent, wxEvent)
8e72b8b5 78 IMPLEMENT_DYNAMIC_CLASS(wxSetCursorEvent, wxEvent)
23f681ec 79 IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent, wxEvent)
574c939e 80 IMPLEMENT_DYNAMIC_CLASS(wxDisplayChangedEvent, wxEvent)
23f681ec 81 IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent, wxCommandEvent)
75299490 82 IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent, wxEvent)
23f681ec
VZ
83 IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent, wxEvent)
84 IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent, wxEvent)
85 IMPLEMENT_DYNAMIC_CLASS(wxWindowCreateEvent, wxEvent)
86 IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent, wxEvent)
b96340e6 87 IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent)
69231000 88 IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent)
a5e84126 89 IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent)
63e819f2 90 IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent)
78c91815 91 IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent)
23f681ec 92#endif // wxUSE_GUI
0b746ba8 93
3ed2104c
VZ
94#if wxUSE_BASE
95
23f681ec
VZ
96const wxEventTable *wxEvtHandler::GetEventTable() const
97 { return &wxEvtHandler::sm_eventTable; }
0b746ba8 98
23f681ec
VZ
99const wxEventTable wxEvtHandler::sm_eventTable =
100 { (const wxEventTable *)NULL, &wxEvtHandler::sm_eventTableEntries[0] };
0b746ba8 101
b5a98acd
VZ
102wxEventHashTable &wxEvtHandler::GetEventHashTable() const
103 { return wxEvtHandler::sm_eventHashTable; }
104
105wxEventHashTable wxEvtHandler::sm_eventHashTable(wxEvtHandler::sm_eventTable);
106
23f681ec 107const wxEventTableEntry wxEvtHandler::sm_eventTableEntries[] =
9aaf9bed 108 { DECLARE_EVENT_TABLE_ENTRY(wxEVT_NULL, 0, 0, (wxObjectEventFunction)NULL, NULL) };
c801d85f 109
1a18887b 110
a0826b11
VZ
111// wxUSE_MEMORY_TRACING considers memory freed from the static objects dtors
112// leaked, so we need to manually clean up all event tables before checking for
113// the memory leaks when using it, however this breaks re-initializing the
114// library (i.e. repeated calls to wxInitialize/wxUninitialize) because the
115// event tables won't be rebuilt the next time, so disable this by default
aa767a45 116#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING
a0826b11 117
afa039f9
JS
118class wxEventTableEntryModule: public wxModule
119{
afa039f9 120public:
a0826b11
VZ
121 wxEventTableEntryModule() { }
122 virtual bool OnInit() { return true; }
123 virtual void OnExit() { wxEventHashTable::ClearAll(); }
124
125 DECLARE_DYNAMIC_CLASS(wxEventTableEntryModule)
afa039f9 126};
a0826b11 127
afa039f9 128IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule)
a0826b11
VZ
129
130#endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING
1a18887b 131
8e193f38
VZ
132// ----------------------------------------------------------------------------
133// global variables
134// ----------------------------------------------------------------------------
135
136// To put pending event handlers
137wxList *wxPendingEvents = (wxList *)NULL;
138
7214297d 139#if wxUSE_THREADS
8e193f38
VZ
140 // protects wxPendingEvents list
141 wxCriticalSection *wxPendingEventsLocker = (wxCriticalSection *)NULL;
7214297d
GL
142#endif
143
cbee8f8d
VZ
144#if !WXWIN_COMPATIBILITY_EVENT_TYPES
145
2e4df4bf
VZ
146// common event types are defined here, other event types are defined by the
147// components which use them
b5a98acd 148
c15d9c85
VS
149const wxEventType wxEVT_FIRST = 10000;
150const wxEventType wxEVT_USER_FIRST = wxEVT_FIRST + 2000;
2e4df4bf 151
461697c2 152DEFINE_EVENT_TYPE(wxEVT_NULL)
886dd7d2
VZ
153DEFINE_EVENT_TYPE(wxEVT_IDLE)
154DEFINE_EVENT_TYPE(wxEVT_SOCKET)
c2ca375c 155DEFINE_EVENT_TYPE(wxEVT_TIMER)
886dd7d2
VZ
156
157#endif // !WXWIN_COMPATIBILITY_EVENT_TYPES
158
159#endif // wxUSE_BASE
160
161#if wxUSE_GUI
162
163#if !WXWIN_COMPATIBILITY_EVENT_TYPES
164
2e4df4bf
VZ
165DEFINE_EVENT_TYPE(wxEVT_COMMAND_BUTTON_CLICKED)
166DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKBOX_CLICKED)
167DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHOICE_SELECTED)
168DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED)
169DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
170DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED)
2e4df4bf
VZ
171DEFINE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED)
172DEFINE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED)
173DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED)
174DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBUTTON_SELECTED)
175DEFINE_EVENT_TYPE(wxEVT_COMMAND_SCROLLBAR_UPDATED)
176DEFINE_EVENT_TYPE(wxEVT_COMMAND_VLBOX_SELECTED)
177DEFINE_EVENT_TYPE(wxEVT_COMMAND_COMBOBOX_SELECTED)
178DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED)
179DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER)
180DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED)
a9a0ceca 181DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED)
0b5eceb6 182
0b5eceb6 183// Mouse event types
2e4df4bf
VZ
184DEFINE_EVENT_TYPE(wxEVT_LEFT_DOWN)
185DEFINE_EVENT_TYPE(wxEVT_LEFT_UP)
186DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DOWN)
187DEFINE_EVENT_TYPE(wxEVT_MIDDLE_UP)
188DEFINE_EVENT_TYPE(wxEVT_RIGHT_DOWN)
189DEFINE_EVENT_TYPE(wxEVT_RIGHT_UP)
190DEFINE_EVENT_TYPE(wxEVT_MOTION)
191DEFINE_EVENT_TYPE(wxEVT_ENTER_WINDOW)
192DEFINE_EVENT_TYPE(wxEVT_LEAVE_WINDOW)
193DEFINE_EVENT_TYPE(wxEVT_LEFT_DCLICK)
194DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DCLICK)
195DEFINE_EVENT_TYPE(wxEVT_RIGHT_DCLICK)
196DEFINE_EVENT_TYPE(wxEVT_SET_FOCUS)
197DEFINE_EVENT_TYPE(wxEVT_KILL_FOCUS)
456bc6d9 198DEFINE_EVENT_TYPE(wxEVT_CHILD_FOCUS)
d2c52078 199DEFINE_EVENT_TYPE(wxEVT_MOUSEWHEEL)
01101e2d
VZ
200DEFINE_EVENT_TYPE(wxEVT_AUX1_DOWN)
201DEFINE_EVENT_TYPE(wxEVT_AUX1_UP)
202DEFINE_EVENT_TYPE(wxEVT_AUX1_DCLICK)
203DEFINE_EVENT_TYPE(wxEVT_AUX2_DOWN)
204DEFINE_EVENT_TYPE(wxEVT_AUX2_UP)
205DEFINE_EVENT_TYPE(wxEVT_AUX2_DCLICK)
0b5eceb6
VZ
206
207// Non-client mouse events
2e4df4bf
VZ
208DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DOWN)
209DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_UP)
210DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DOWN)
211DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_UP)
212DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DOWN)
213DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_UP)
214DEFINE_EVENT_TYPE(wxEVT_NC_MOTION)
215DEFINE_EVENT_TYPE(wxEVT_NC_ENTER_WINDOW)
216DEFINE_EVENT_TYPE(wxEVT_NC_LEAVE_WINDOW)
217DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DCLICK)
218DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DCLICK)
219DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DCLICK)
0b5eceb6
VZ
220
221// Character input event type
2e4df4bf
VZ
222DEFINE_EVENT_TYPE(wxEVT_CHAR)
223DEFINE_EVENT_TYPE(wxEVT_CHAR_HOOK)
224DEFINE_EVENT_TYPE(wxEVT_NAVIGATION_KEY)
225DEFINE_EVENT_TYPE(wxEVT_KEY_DOWN)
226DEFINE_EVENT_TYPE(wxEVT_KEY_UP)
5048c832
JS
227#if wxUSE_HOTKEY
228DEFINE_EVENT_TYPE(wxEVT_HOTKEY)
229#endif
0b5eceb6
VZ
230
231// Set cursor event
2e4df4bf 232DEFINE_EVENT_TYPE(wxEVT_SET_CURSOR)
0b5eceb6
VZ
233
234// wxScrollbar and wxSlider event identifiers
2e4df4bf
VZ
235DEFINE_EVENT_TYPE(wxEVT_SCROLL_TOP)
236DEFINE_EVENT_TYPE(wxEVT_SCROLL_BOTTOM)
237DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEUP)
238DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEDOWN)
239DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEUP)
240DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEDOWN)
241DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBTRACK)
242DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBRELEASE)
d15b1f85 243DEFINE_EVENT_TYPE(wxEVT_SCROLL_CHANGED)
0b5eceb6
VZ
244
245// Scroll events from wxWindow
2e4df4bf
VZ
246DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_TOP)
247DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_BOTTOM)
248DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEUP)
249DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEDOWN)
250DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEUP)
251DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEDOWN)
252DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBTRACK)
253DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBRELEASE)
0b5eceb6
VZ
254
255// System events
2e4df4bf 256DEFINE_EVENT_TYPE(wxEVT_SIZE)
5706de1c 257DEFINE_EVENT_TYPE(wxEVT_SIZING)
2e4df4bf 258DEFINE_EVENT_TYPE(wxEVT_MOVE)
5706de1c 259DEFINE_EVENT_TYPE(wxEVT_MOVING)
aa767a45
JS
260DEFINE_EVENT_TYPE(wxEVT_MOVE_START)
261DEFINE_EVENT_TYPE(wxEVT_MOVE_END)
2e4df4bf
VZ
262DEFINE_EVENT_TYPE(wxEVT_CLOSE_WINDOW)
263DEFINE_EVENT_TYPE(wxEVT_END_SESSION)
264DEFINE_EVENT_TYPE(wxEVT_QUERY_END_SESSION)
afafd942 265DEFINE_EVENT_TYPE(wxEVT_HIBERNATE)
2e4df4bf 266DEFINE_EVENT_TYPE(wxEVT_ACTIVATE_APP)
2e4df4bf
VZ
267DEFINE_EVENT_TYPE(wxEVT_ACTIVATE)
268DEFINE_EVENT_TYPE(wxEVT_CREATE)
269DEFINE_EVENT_TYPE(wxEVT_DESTROY)
270DEFINE_EVENT_TYPE(wxEVT_SHOW)
271DEFINE_EVENT_TYPE(wxEVT_ICONIZE)
272DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE)
273DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED)
63e819f2 274DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST)
2e4df4bf
VZ
275DEFINE_EVENT_TYPE(wxEVT_PAINT)
276DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
277DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
278DEFINE_EVENT_TYPE(wxEVT_PAINT_ICON)
ccef86c7
VZ
279DEFINE_EVENT_TYPE(wxEVT_MENU_OPEN)
280DEFINE_EVENT_TYPE(wxEVT_MENU_CLOSE)
2e4df4bf 281DEFINE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT)
2e4df4bf
VZ
282DEFINE_EVENT_TYPE(wxEVT_CONTEXT_MENU)
283DEFINE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED)
574c939e 284DEFINE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED)
2e4df4bf
VZ
285DEFINE_EVENT_TYPE(wxEVT_SETTING_CHANGED)
286DEFINE_EVENT_TYPE(wxEVT_QUERY_NEW_PALETTE)
287DEFINE_EVENT_TYPE(wxEVT_PALETTE_CHANGED)
288DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_DOWN)
289DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_UP)
290DEFINE_EVENT_TYPE(wxEVT_JOY_MOVE)
291DEFINE_EVENT_TYPE(wxEVT_JOY_ZMOVE)
292DEFINE_EVENT_TYPE(wxEVT_DROP_FILES)
293DEFINE_EVENT_TYPE(wxEVT_DRAW_ITEM)
294DEFINE_EVENT_TYPE(wxEVT_MEASURE_ITEM)
295DEFINE_EVENT_TYPE(wxEVT_COMPARE_ITEM)
296DEFINE_EVENT_TYPE(wxEVT_INIT_DIALOG)
2e4df4bf 297DEFINE_EVENT_TYPE(wxEVT_UPDATE_UI)
0b5eceb6 298
78c91815
VZ
299// Clipboard events
300DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY)
301DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT)
302DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE)
303
0b5eceb6
VZ
304// Generic command events
305// Note: a click is a higher-level event than button down/up
2e4df4bf
VZ
306DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK)
307DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_DCLICK)
308DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_CLICK)
309DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_DCLICK)
310DEFINE_EVENT_TYPE(wxEVT_COMMAND_SET_FOCUS)
311DEFINE_EVENT_TYPE(wxEVT_COMMAND_KILL_FOCUS)
312DEFINE_EVENT_TYPE(wxEVT_COMMAND_ENTER)
0b5eceb6
VZ
313
314// Help events
2e4df4bf
VZ
315DEFINE_EVENT_TYPE(wxEVT_HELP)
316DEFINE_EVENT_TYPE(wxEVT_DETAILED_HELP)
6164f93c
VZ
317
318#endif // !WXWIN_COMPATIBILITY_EVENT_TYPES
319
886dd7d2
VZ
320#endif // wxUSE_GUI
321
322#if wxUSE_BASE
323
b46b1d59
VZ
324wxIdleMode wxIdleEvent::sm_idleMode = wxIDLE_PROCESS_ALL;
325
6164f93c
VZ
326// ============================================================================
327// implementation
328// ============================================================================
0b5eceb6 329
0b5eceb6
VZ
330// ----------------------------------------------------------------------------
331// event initialization
332// ----------------------------------------------------------------------------
333
334int wxNewEventType()
335{
336 // MT-FIXME
337 static int s_lastUsedEventType = wxEVT_FIRST;
338
339 return s_lastUsedEventType++;
340}
341
8e193f38
VZ
342// ----------------------------------------------------------------------------
343// wxEvent
344// ----------------------------------------------------------------------------
345
c801d85f 346/*
77ffb593 347 * General wxWidgets events, covering
c801d85f
KB
348 * all interesting things that might happen (button clicking, resizing,
349 * setting text in widgets, etc.).
350 *
351 * For each completely new event type, derive a new event class.
352 *
353 */
354
8e72b8b5 355wxEvent::wxEvent(int theId, wxEventType commandType )
c801d85f 356{
8e72b8b5 357 m_eventType = commandType;
0b746ba8 358 m_eventObject = (wxObject *) NULL;
0b746ba8
VZ
359 m_timeStamp = 0;
360 m_id = theId;
1c624631 361 m_skipped = false;
0b746ba8 362 m_callbackUserData = (wxObject *) NULL;
1c624631 363 m_isCommandEvent = false;
1648d51b 364 m_propagationLevel = wxEVENT_PROPAGATE_NONE;
c801d85f
KB
365}
366
8e72b8b5 367wxEvent::wxEvent(const wxEvent &src)
a34ef99b 368 : wxObject(src)
e6a6feba
GD
369 , m_eventObject(src.m_eventObject)
370 , m_eventType(src.m_eventType)
371 , m_timeStamp(src.m_timeStamp)
372 , m_id(src.m_id)
373 , m_callbackUserData(src.m_callbackUserData)
6fd5903a 374 , m_propagationLevel(src.m_propagationLevel)
e6a6feba
GD
375 , m_skipped(src.m_skipped)
376 , m_isCommandEvent(src.m_isCommandEvent)
a737331d 377{
a737331d
GL
378}
379
3ed2104c
VZ
380#endif // wxUSE_BASE
381
e90c1d2a
VZ
382#if wxUSE_GUI
383
c801d85f
KB
384/*
385 * Command events
386 *
387 */
388
21eefb76
VZ
389#ifdef __VISUALC__
390 // 'this' : used in base member initializer list (for m_commandString)
391 #pragma warning(disable:4355)
392#endif
393
7798a18e 394wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
b5a98acd 395 : wxEvent(theId, commandType)
c801d85f 396{
0b746ba8
VZ
397 m_clientData = (char *) NULL;
398 m_clientObject = (wxClientData *) NULL;
399 m_extraLong = 0;
400 m_commandInt = 0;
1c624631 401 m_isCommandEvent = true;
1648d51b
VZ
402
403 // the command events are propagated upwards by default
404 m_propagationLevel = wxEVENT_PROPAGATE_MAX;
c801d85f
KB
405}
406
21eefb76
VZ
407#ifdef __VISUALC__
408 #pragma warning(default:4355)
409#endif
410
ab1931f9
KH
411wxString wxCommandEvent::GetString() const
412{
413 if(m_eventType != wxEVT_COMMAND_TEXT_UPDATED || !m_eventObject)
414 return m_cmdString;
415 else
416 {
89438177 417#if wxUSE_TEXTCTRL
ab1931f9
KH
418 wxTextCtrl *txt = wxDynamicCast(m_eventObject, wxTextCtrl);
419 if(txt)
420 return txt->GetValue();
421 else
89438177 422#endif // wxUSE_TEXTCTRL
ab1931f9
KH
423 return m_cmdString;
424 }
425}
426
0b30bb0b
JS
427/*
428 * UI update events
429 */
430
431#if wxUSE_LONGLONG
e39af974 432wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0;
0b30bb0b
JS
433#endif
434
e39af974
JS
435long wxUpdateUIEvent::sm_updateInterval = 0;
436
437wxUpdateUIMode wxUpdateUIEvent::sm_updateMode = wxUPDATE_UI_PROCESS_ALL;
0b30bb0b
JS
438
439// Can we update?
a7bc03c9 440bool wxUpdateUIEvent::CanUpdate(wxWindowBase *win)
0b30bb0b 441{
e39af974
JS
442 // Don't update if we've switched global updating off
443 // and this window doesn't support updates.
444 if (win &&
445 (GetMode() == wxUPDATE_UI_PROCESS_SPECIFIED &&
446 ((win->GetExtraStyle() & wxWS_EX_PROCESS_UI_UPDATES) == 0)))
1c624631 447 return false;
b5a98acd 448
e39af974 449 if (sm_updateInterval == -1)
1c624631 450 return false;
534b127c
WS
451
452 if (sm_updateInterval == 0)
1c624631 453 return true;
534b127c 454
0b30bb0b 455#if wxUSE_STOPWATCH && wxUSE_LONGLONG
534b127c
WS
456 wxLongLong now = wxGetLocalTimeMillis();
457 if (now > (sm_lastUpdate + sm_updateInterval))
458 {
1c624631 459 return true;
0b30bb0b 460 }
534b127c 461
1c624631 462 return false;
534b127c
WS
463#else
464 // If we don't have wxStopWatch or wxLongLong, we
465 // should err on the safe side and update now anyway.
466 return true;
467#endif
0b30bb0b
JS
468}
469
470// Reset the update time to provide a delay until the next
471// time we should update
472void wxUpdateUIEvent::ResetUpdateTime()
473{
474#if wxUSE_STOPWATCH && wxUSE_LONGLONG
e39af974 475 if (sm_updateInterval > 0)
0b30bb0b
JS
476 {
477 wxLongLong now = wxGetLocalTimeMillis();
e39af974 478 if (now > (sm_lastUpdate + sm_updateInterval))
0b30bb0b 479 {
e39af974 480 sm_lastUpdate = now;
0b30bb0b
JS
481 }
482 }
483#endif
484}
485
c801d85f
KB
486/*
487 * Scroll events
488 */
489
0b746ba8
VZ
490wxScrollEvent::wxScrollEvent(wxEventType commandType,
491 int id,
492 int pos,
493 int orient)
e6a6feba 494 : wxCommandEvent(commandType, id)
c801d85f 495{
0b746ba8
VZ
496 m_extraLong = orient;
497 m_commandInt = pos;
c801d85f
KB
498}
499
d1367c3d
RR
500/*
501 * ScrollWin events
502 */
503
504wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
505 int pos,
506 int orient)
d1367c3d 507{
c5b42c87 508 m_eventType = commandType;
d1367c3d
RR
509 m_extraLong = orient;
510 m_commandInt = pos;
511}
512
c801d85f
KB
513/*
514 * Mouse events
515 *
516 */
517
7798a18e 518wxMouseEvent::wxMouseEvent(wxEventType commandType)
c801d85f 519{
0b746ba8 520 m_eventType = commandType;
8866abbb
VZ
521
522 m_x = 0;
523 m_y = 0;
524
1c624631 525 m_leftDown = false;
1c624631 526 m_middleDown = false;
8866abbb 527 m_rightDown = false;
01101e2d
VZ
528 m_aux1Down = false;
529 m_aux2Down = false;
8866abbb
VZ
530
531 m_controlDown = false;
532 m_shiftDown = false;
533 m_altDown = false;
534 m_metaDown = false;
535
536 m_clickCount = -1;
537
d2c52078
RD
538 m_wheelRotation = 0;
539 m_wheelDelta = 0;
540 m_linesPerAction = 0;
aea37008 541 m_wheelAxis = 0;
c801d85f
KB
542}
543
abcbaea7
VZ
544void wxMouseEvent::Assign(const wxMouseEvent& event)
545{
9a1725c4 546 m_eventType = event.m_eventType;
92309201 547
abcbaea7
VZ
548 m_x = event.m_x;
549 m_y = event.m_y;
550
551 m_leftDown = event.m_leftDown;
552 m_middleDown = event.m_middleDown;
553 m_rightDown = event.m_rightDown;
01101e2d
VZ
554 m_aux1Down = event.m_aux1Down;
555 m_aux2Down = event.m_aux2Down;
abcbaea7
VZ
556
557 m_controlDown = event.m_controlDown;
558 m_shiftDown = event.m_shiftDown;
559 m_altDown = event.m_altDown;
560 m_metaDown = event.m_metaDown;
561
562 m_wheelRotation = event.m_wheelRotation;
563 m_wheelDelta = event.m_wheelDelta;
564 m_linesPerAction = event.m_linesPerAction;
aea37008 565 m_wheelAxis = event.m_wheelAxis;
abcbaea7
VZ
566}
567
3e89999c 568// return true if was a button dclick event
c801d85f
KB
569bool wxMouseEvent::ButtonDClick(int but) const
570{
0b746ba8
VZ
571 switch (but)
572 {
3e89999c
VZ
573 default:
574 wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDClick"));
575 // fall through
576
577 case wxMOUSE_BTN_ANY:
01101e2d
VZ
578 return (LeftDClick() || MiddleDClick() || RightDClick() ||
579 Aux1DClick() || Aux2DClick());
3e89999c
VZ
580
581 case wxMOUSE_BTN_LEFT:
0b746ba8 582 return LeftDClick();
3e89999c
VZ
583
584 case wxMOUSE_BTN_MIDDLE:
0b746ba8 585 return MiddleDClick();
3e89999c
VZ
586
587 case wxMOUSE_BTN_RIGHT:
0b746ba8 588 return RightDClick();
01101e2d
VZ
589
590 case wxMOUSE_BTN_AUX1:
591 return Aux1DClick();
592
593 case wxMOUSE_BTN_AUX2:
594 return Aux2DClick();
0b746ba8 595 }
c801d85f
KB
596}
597
3e89999c 598// return true if was a button down event
c801d85f
KB
599bool wxMouseEvent::ButtonDown(int but) const
600{
0b746ba8
VZ
601 switch (but)
602 {
3e89999c
VZ
603 default:
604 wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDown"));
605 // fall through
606
607 case wxMOUSE_BTN_ANY:
01101e2d
VZ
608 return (LeftDown() || MiddleDown() || RightDown() ||
609 Aux1Down() || Aux2Down());
3e89999c
VZ
610
611 case wxMOUSE_BTN_LEFT:
0b746ba8 612 return LeftDown();
3e89999c
VZ
613
614 case wxMOUSE_BTN_MIDDLE:
0b746ba8 615 return MiddleDown();
3e89999c
VZ
616
617 case wxMOUSE_BTN_RIGHT:
0b746ba8 618 return RightDown();
01101e2d
VZ
619
620 case wxMOUSE_BTN_AUX1:
621 return Aux1Down();
622
623 case wxMOUSE_BTN_AUX2:
624 return Aux2Down();
0b746ba8 625 }
c801d85f
KB
626}
627
3e89999c 628// return true if was a button up event
c801d85f
KB
629bool wxMouseEvent::ButtonUp(int but) const
630{
1e6feb95
VZ
631 switch (but)
632 {
3e89999c
VZ
633 default:
634 wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonUp"));
635 // fall through
636
637 case wxMOUSE_BTN_ANY:
01101e2d
VZ
638 return (LeftUp() || MiddleUp() || RightUp() ||
639 Aux1Up() || Aux2Up());
3e89999c
VZ
640
641 case wxMOUSE_BTN_LEFT:
0b746ba8 642 return LeftUp();
3e89999c
VZ
643
644 case wxMOUSE_BTN_MIDDLE:
0b746ba8 645 return MiddleUp();
3e89999c
VZ
646
647 case wxMOUSE_BTN_RIGHT:
0b746ba8 648 return RightUp();
01101e2d
VZ
649
650 case wxMOUSE_BTN_AUX1:
651 return Aux1Up();
652
653 case wxMOUSE_BTN_AUX2:
654 return Aux2Up();
0b746ba8 655 }
c801d85f
KB
656}
657
3e89999c 658// return true if the given button is currently changing state
c801d85f
KB
659bool wxMouseEvent::Button(int but) const
660{
1e6feb95
VZ
661 switch (but)
662 {
0b746ba8 663 default:
223d09f6 664 wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::Button"));
3e89999c
VZ
665 // fall through
666
667 case wxMOUSE_BTN_ANY:
668 return ButtonUp(wxMOUSE_BTN_ANY) ||
669 ButtonDown(wxMOUSE_BTN_ANY) ||
670 ButtonDClick(wxMOUSE_BTN_ANY);
671
672 case wxMOUSE_BTN_LEFT:
673 return LeftDown() || LeftUp() || LeftDClick();
674
675 case wxMOUSE_BTN_MIDDLE:
676 return MiddleDown() || MiddleUp() || MiddleDClick();
677
678 case wxMOUSE_BTN_RIGHT:
679 return RightDown() || RightUp() || RightDClick();
01101e2d
VZ
680
681 case wxMOUSE_BTN_AUX1:
682 return Aux1Down() || Aux1Up() || Aux1DClick();
683
684 case wxMOUSE_BTN_AUX2:
685 return Aux2Down() || Aux2Up() || Aux2DClick();
0b746ba8 686 }
c801d85f
KB
687}
688
689bool wxMouseEvent::ButtonIsDown(int but) const
690{
1e6feb95
VZ
691 switch (but)
692 {
3e89999c
VZ
693 default:
694 wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonIsDown"));
695 // fall through
696
697 case wxMOUSE_BTN_ANY:
01101e2d 698 return LeftIsDown() || MiddleIsDown() || RightIsDown() || Aux1Down() || Aux2Down();
3e89999c
VZ
699
700 case wxMOUSE_BTN_LEFT:
0b746ba8 701 return LeftIsDown();
3e89999c
VZ
702
703 case wxMOUSE_BTN_MIDDLE:
0b746ba8 704 return MiddleIsDown();
3e89999c
VZ
705
706 case wxMOUSE_BTN_RIGHT:
0b746ba8 707 return RightIsDown();
01101e2d
VZ
708
709 case wxMOUSE_BTN_AUX1:
710 return Aux1IsDown();
711
712 case wxMOUSE_BTN_AUX2:
713 return Aux2IsDown();
0b746ba8 714 }
c801d85f
KB
715}
716
1e6feb95
VZ
717int wxMouseEvent::GetButton() const
718{
01101e2d 719 for ( int i = 1; i < wxMOUSE_BTN_MAX; i++ )
1e6feb95
VZ
720 {
721 if ( Button(i) )
722 {
723 return i;
724 }
725 }
726
3e89999c 727 return wxMOUSE_BTN_NONE;
1e6feb95
VZ
728}
729
c801d85f
KB
730// Find the logical position of the event given the DC
731wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const
732{
0757d27c
JS
733 wxPoint pt(dc.DeviceToLogicalX(m_x), dc.DeviceToLogicalY(m_y));
734 return pt;
c801d85f
KB
735}
736
737
738/*
8e72b8b5 739 * Keyboard event
c801d85f
KB
740 *
741 */
742
7798a18e 743wxKeyEvent::wxKeyEvent(wxEventType type)
c801d85f 744{
0b746ba8 745 m_eventType = type;
1c624631
VZ
746 m_shiftDown = false;
747 m_controlDown = false;
748 m_metaDown = false;
749 m_altDown = false;
0b746ba8 750 m_keyCode = 0;
b0e813a0 751 m_scanCode = 0;
2b5f62a0
VZ
752#if wxUSE_UNICODE
753 m_uniChar = 0;
754#endif
c801d85f
KB
755}
756
92309201 757wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt)
2b5f62a0
VZ
758 : wxEvent(evt)
759{
760 m_x = evt.m_x;
761 m_y = evt.m_y;
762
763 m_keyCode = evt.m_keyCode;
764
765 m_controlDown = evt.m_controlDown;
766 m_shiftDown = evt.m_shiftDown;
767 m_altDown = evt.m_altDown;
768 m_metaDown = evt.m_metaDown;
769 m_scanCode = evt.m_scanCode;
770 m_rawCode = evt.m_rawCode;
771 m_rawFlags = evt.m_rawFlags;
92309201 772
2b5f62a0
VZ
773#if wxUSE_UNICODE
774 m_uniChar = evt.m_uniChar;
775#endif
776}
12a3f227 777
ca3e85cf 778#if WXWIN_COMPATIBILITY_2_6
12a3f227
RL
779long wxKeyEvent::KeyCode() const
780{
781 return m_keyCode;
782}
ca3e85cf 783#endif // WXWIN_COMPATIBILITY_2_6
12a3f227 784
42e69d6b 785wxWindowCreateEvent::wxWindowCreateEvent(wxWindow *win)
42e69d6b 786{
cfe17b74 787 SetEventType(wxEVT_CREATE);
42e69d6b
VZ
788 SetEventObject(win);
789}
790
791wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow *win)
42e69d6b 792{
cfe17b74 793 SetEventType(wxEVT_DESTROY);
42e69d6b
VZ
794 SetEventObject(win);
795}
796
456bc6d9
VZ
797wxChildFocusEvent::wxChildFocusEvent(wxWindow *win)
798 : wxCommandEvent(wxEVT_CHILD_FOCUS)
799{
800 SetEventObject(win);
801}
802
b107e8d5
VZ
803// ----------------------------------------------------------------------------
804// wxHelpEvent
805// ----------------------------------------------------------------------------
806
807/* static */
808wxHelpEvent::Origin wxHelpEvent::GuessOrigin(Origin origin)
809{
810 if ( origin == Origin_Unknown )
811 {
812 // assume that the event comes from the help button if it's not from
813 // keyboard and that pressing F1 always results in the help event
814 origin = wxGetKeyState(WXK_F1) ? Origin_Keyboard : Origin_HelpButton;
815 }
816
817 return origin;
818}
819
dd070522
VZ
820#endif // wxUSE_GUI
821
9416681d
VS
822
823#if wxUSE_BASE
824
b5a98acd
VZ
825// ----------------------------------------------------------------------------
826// wxEventHashTable
827// ----------------------------------------------------------------------------
828
afa039f9
JS
829static const int EVENT_TYPE_TABLE_INIT_SIZE = 31; // Not too big not too small...
830
831wxEventHashTable* wxEventHashTable::sm_first = NULL;
b5a98acd
VZ
832
833wxEventHashTable::wxEventHashTable(const wxEventTable &table)
834 : m_table(table),
1c624631 835 m_rebuildHash(true)
b5a98acd
VZ
836{
837 AllocEventTypeTable(EVENT_TYPE_TABLE_INIT_SIZE);
1a18887b 838
afa039f9
JS
839 m_next = sm_first;
840 if (m_next)
841 m_next->m_previous = this;
842 sm_first = this;
b5a98acd
VZ
843}
844
845wxEventHashTable::~wxEventHashTable()
afa039f9
JS
846{
847 if (m_next)
848 m_next->m_previous = m_previous;
849 if (m_previous)
850 m_previous->m_next = m_next;
851 if (sm_first == this)
852 sm_first = m_next;
1a18887b 853
afa039f9
JS
854 Clear();
855}
856
857void wxEventHashTable::Clear()
b5a98acd 858{
a0826b11 859 for ( size_t i = 0; i < m_size; i++ )
b5a98acd
VZ
860 {
861 EventTypeTablePointer eTTnode = m_eventTypeTable[i];
a0826b11 862 delete eTTnode;
b5a98acd
VZ
863 }
864
a0826b11 865 delete[] m_eventTypeTable;
afa039f9 866 m_eventTypeTable = NULL;
a0826b11 867
afa039f9
JS
868 m_size = 0;
869}
870
aa767a45 871#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING
a0826b11 872
afa039f9
JS
873// Clear all tables
874void wxEventHashTable::ClearAll()
875{
876 wxEventHashTable* table = sm_first;
877 while (table)
878 {
879 table->Clear();
880 table = table->m_next;
881 }
b5a98acd
VZ
882}
883
a0826b11
VZ
884#endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING
885
b5a98acd
VZ
886bool wxEventHashTable::HandleEvent(wxEvent &event, wxEvtHandler *self)
887{
888 if (m_rebuildHash)
889 {
890 InitHashTable();
1c624631 891 m_rebuildHash = false;
b5a98acd 892 }
1a18887b 893
afa039f9 894 if (!m_eventTypeTable)
1a18887b 895 return false;
b5a98acd
VZ
896
897 // Find all entries for the given event type.
898 wxEventType eventType = event.GetEventType();
899 const EventTypeTablePointer eTTnode = m_eventTypeTable[eventType % m_size];
900 if (eTTnode && eTTnode->eventType == eventType)
901 {
902 // Now start the search for an event handler
903 // that can handle an event with the given ID.
1c624631
VZ
904 const wxEventTableEntryPointerArray&
905 eventEntryTable = eTTnode->eventEntryTable;
b5a98acd 906
1c624631
VZ
907 const size_t count = eventEntryTable.GetCount();
908 for (size_t n = 0; n < count; n++)
b5a98acd 909 {
1c624631
VZ
910 if ( wxEvtHandler::
911 ProcessEventIfMatches(*eventEntryTable[n], self, event) )
b5a98acd 912 {
1c624631 913 return true;
b5a98acd
VZ
914 }
915 }
b5a98acd
VZ
916 }
917
1c624631 918 return false;
b5a98acd
VZ
919}
920
921void wxEventHashTable::InitHashTable()
922{
923 // Loop over the event tables and all its base tables.
924 const wxEventTable *table = &m_table;
925 while (table)
926 {
927 // Retrieve all valid event handler entries
928 const wxEventTableEntry *entry = table->entries;
929 while (entry->m_fn != 0)
930 {
931 // Add the event entry in the Hash.
932 AddEntry(*entry);
933
934 entry++;
935 }
936
937 table = table->baseTable;
938 }
939
940 // Lets free some memory.
941 size_t i;
942 for(i = 0; i < m_size; i++)
943 {
944 EventTypeTablePointer eTTnode = m_eventTypeTable[i];
945 if (eTTnode)
946 {
947 eTTnode->eventEntryTable.Shrink();
948 }
949 }
950}
951
952void wxEventHashTable::AddEntry(const wxEventTableEntry &entry)
953{
afa039f9
JS
954 // This might happen 'accidentally' as the app is exiting
955 if (!m_eventTypeTable)
956 return;
1a18887b 957
b5a98acd
VZ
958 EventTypeTablePointer *peTTnode = &m_eventTypeTable[entry.m_eventType % m_size];
959 EventTypeTablePointer eTTnode = *peTTnode;
960
961 if (eTTnode)
962 {
963 if (eTTnode->eventType != entry.m_eventType)
964 {
965 // Resize the table!
966 GrowEventTypeTable();
967 // Try again to add it.
968 AddEntry(entry);
969 return;
970 }
971 }
972 else
973 {
974 eTTnode = new EventTypeTable;
975 eTTnode->eventType = entry.m_eventType;
976 *peTTnode = eTTnode;
977 }
978
979 // Fill all hash entries between entry.m_id and entry.m_lastId...
980 eTTnode->eventEntryTable.Add(&entry);
981}
982
983void wxEventHashTable::AllocEventTypeTable(size_t size)
984{
985 m_eventTypeTable = new EventTypeTablePointer[size];
986 memset((void *)m_eventTypeTable, 0, sizeof(EventTypeTablePointer)*size);
987 m_size = size;
988}
989
990void wxEventHashTable::GrowEventTypeTable()
991{
992 size_t oldSize = m_size;
993 EventTypeTablePointer *oldEventTypeTable = m_eventTypeTable;
994
995 // TODO: Search the most optimal grow sequence
996 AllocEventTypeTable(/* GetNextPrime(oldSize) */oldSize*2+1);
997
998 for ( size_t i = 0; i < oldSize; /* */ )
999 {
1000 EventTypeTablePointer eTToldNode = oldEventTypeTable[i];
1001 if (eTToldNode)
1002 {
1003 EventTypeTablePointer *peTTnode = &m_eventTypeTable[eTToldNode->eventType % m_size];
1004 EventTypeTablePointer eTTnode = *peTTnode;
1005
1006 // Check for collision, we don't want any.
1007 if (eTTnode)
1008 {
1009 GrowEventTypeTable();
1010 continue; // Don't increment the counter,
1011 // as we still need to add this element.
1012 }
1013 else
1014 {
1015 // Get the old value and put it in the new table.
1016 *peTTnode = oldEventTypeTable[i];
1017 }
1018 }
1019
1020 i++;
1021 }
1022
1023 delete[] oldEventTypeTable;
1024}
1025
afa039f9 1026
456bc6d9
VZ
1027// ----------------------------------------------------------------------------
1028// wxEvtHandler
1029// ----------------------------------------------------------------------------
1030
c801d85f
KB
1031/*
1032 * Event handler
1033 */
1034
0b746ba8 1035wxEvtHandler::wxEvtHandler()
c801d85f 1036{
0b746ba8
VZ
1037 m_nextHandler = (wxEvtHandler *) NULL;
1038 m_previousHandler = (wxEvtHandler *) NULL;
1c624631 1039 m_enabled = true;
0b746ba8 1040 m_dynamicEvents = (wxList *) NULL;
8e193f38 1041 m_pendingEvents = (wxList *) NULL;
7214297d 1042#if wxUSE_THREADS
41404da7 1043# if !defined(__VISAGECPP__)
8e193f38 1044 m_eventsLocker = new wxCriticalSection;
41404da7 1045# endif
7214297d 1046#endif
aa767a45 1047
b88c44e7
RD
1048 // no client data (yet)
1049 m_clientData = NULL;
1050 m_clientDataType = wxClientData_None;
c801d85f
KB
1051}
1052
0b746ba8 1053wxEvtHandler::~wxEvtHandler()
c801d85f 1054{
0b746ba8
VZ
1055 // Takes itself out of the list of handlers
1056 if (m_previousHandler)
1057 m_previousHandler->m_nextHandler = m_nextHandler;
1058
1059 if (m_nextHandler)
1060 m_nextHandler->m_previousHandler = m_previousHandler;
1061
1062 if (m_dynamicEvents)
fe71f65c 1063 {
3c448b2e
VZ
1064 for ( wxList::iterator it = m_dynamicEvents->begin(),
1065 end = m_dynamicEvents->end();
1066 it != end;
1067 ++it )
0b746ba8 1068 {
2e4df4bf 1069#if WXWIN_COMPATIBILITY_EVENT_TYPES
df5168c4 1070 wxEventTableEntry *entry = (wxEventTableEntry*)*it;
2e4df4bf 1071#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
df5168c4 1072 wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)*it;
2e4df4bf
VZ
1073#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
1074
1075 if (entry->m_callbackUserData)
1076 delete entry->m_callbackUserData;
0b746ba8 1077 delete entry;
0b746ba8
VZ
1078 }
1079 delete m_dynamicEvents;
1080 };
7214297d 1081
5875d39c
VZ
1082 if (m_pendingEvents)
1083 m_pendingEvents->DeleteContents(true);
8e193f38 1084 delete m_pendingEvents;
7214297d 1085
8e193f38 1086#if wxUSE_THREADS
41404da7 1087# if !defined(__VISAGECPP__)
7214297d 1088 delete m_eventsLocker;
41404da7 1089# endif
b5a98acd 1090
083f7497
JS
1091 // Remove us from wxPendingEvents if necessary.
1092 if(wxPendingEventsLocker)
1093 wxENTER_CRIT_SECT(*wxPendingEventsLocker);
5d9d1b88
RR
1094 if ( wxPendingEvents )
1095 {
1096 // Delete all occurences of this from the list of pending events
1097 while (wxPendingEvents->DeleteObject(this)) { } // Do nothing
083f7497
JS
1098 }
1099 if(wxPendingEventsLocker)
1100 wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
7214297d 1101#endif
b88c44e7
RD
1102
1103 // we only delete object data, not untyped
1104 if ( m_clientDataType == wxClientData_Object )
1105 delete m_clientObject;
c801d85f
KB
1106}
1107
7214297d 1108#if wxUSE_THREADS
aadbdf11 1109
76bfdc9a 1110bool wxEvtHandler::ProcessThreadEvent(const wxEvent& event)
7214297d 1111{
7214297d 1112 // check that we are really in a child thread
8e193f38
VZ
1113 wxASSERT_MSG( !wxThread::IsMain(),
1114 wxT("use ProcessEvent() in main thread") );
1115
1116 AddPendingEvent(event);
7214297d 1117
1c624631 1118 return true;
8e193f38
VZ
1119}
1120
1c624631
VZ
1121void wxEvtHandler::ClearEventLocker()
1122{
1123#if !defined(__VISAGECPP__)
1124 delete m_eventsLocker;
1125 m_eventsLocker = NULL;
1126#endif
4115960d 1127}
1c624631 1128
8e193f38
VZ
1129#endif // wxUSE_THREADS
1130
76bfdc9a 1131void wxEvtHandler::AddPendingEvent(const wxEvent& event)
8e193f38 1132{
16c1f79c
RR
1133 // 1) Add event to list of pending events of this event handler
1134
7a5c8ac4
VZ
1135 wxEvent *eventCopy = event.Clone();
1136
1137 // we must be able to copy the events here so the event class must
1138 // implement Clone() properly instead of just providing a NULL stab for it
1139 wxCHECK_RET( eventCopy,
1140 _T("events of this type aren't supposed to be posted") );
1141
cd30330f 1142 wxENTER_CRIT_SECT( Lock() );
16c1f79c 1143
8e193f38
VZ
1144 if ( !m_pendingEvents )
1145 m_pendingEvents = new wxList;
7214297d 1146
7a5c8ac4 1147 m_pendingEvents->Append(eventCopy);
7214297d 1148
cd30330f 1149 wxLEAVE_CRIT_SECT( Lock() );
16c1f79c
RR
1150
1151 // 2) Add this event handler to list of event handlers that
1152 // have pending events.
cfe17b74 1153
b568d04f 1154 wxENTER_CRIT_SECT(*wxPendingEventsLocker);
72cdf4c9 1155
8e193f38
VZ
1156 if ( !wxPendingEvents )
1157 wxPendingEvents = new wxList;
4d3a259a 1158 wxPendingEvents->Append(this);
72cdf4c9 1159
ce6d2511 1160 wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
6164f93c 1161
90e572f1 1162 // 3) Inform the system that new pending events are somewhere,
16c1f79c 1163 // and that these should be processed in idle time.
bf9e3e73 1164 wxWakeUpIdle();
7214297d
GL
1165}
1166
1167void wxEvtHandler::ProcessPendingEvents()
1168{
5fa150e2
RR
1169 // this method is only called by wxApp if this handler does have
1170 // pending events
77e7c556
VZ
1171 wxCHECK_RET( m_pendingEvents,
1172 wxT("Please call wxApp::ProcessPendingEvents() instead") );
aa767a45 1173
cd30330f 1174 wxENTER_CRIT_SECT( Lock() );
8e193f38 1175
7b0d5c59
VZ
1176 // we leave the loop once we have processed all events that were present at
1177 // the start of ProcessPendingEvents because otherwise we could get into
1178 // infinite loop if the pending event handler execution resulted in another
1179 // event being posted
1180 size_t n = m_pendingEvents->size();
1181 for ( wxList::compatibility_iterator node = m_pendingEvents->GetFirst();
1182 node;
1183 node = m_pendingEvents->GetFirst() )
8e193f38 1184 {
b1d4dd7a 1185 wxEvent *event = (wxEvent *)node->GetData();
7b0d5c59 1186
5875d39c
VZ
1187 // It's importan we remove event from list before processing it.
1188 // Else a nested event loop, for example from a modal dialog, might
1189 // process the same event again.
5fa150e2 1190
5875d39c
VZ
1191 m_pendingEvents->Erase(node);
1192
cd30330f 1193 wxLEAVE_CRIT_SECT( Lock() );
7b0d5c59 1194
8e193f38 1195 ProcessEvent(*event);
5fa150e2 1196
5875d39c 1197 delete event;
7b0d5c59 1198
cd30330f 1199 wxENTER_CRIT_SECT( Lock() );
cfe17b74 1200
8d7eaf91 1201 if ( --n == 0 )
18dbea4d 1202 break;
7214297d 1203 }
cfe17b74 1204
cd30330f 1205 wxLEAVE_CRIT_SECT( Lock() );
7214297d 1206}
7214297d 1207
c801d85f
KB
1208/*
1209 * Event table stuff
1210 */
1c624631
VZ
1211/* static */ bool
1212wxEvtHandler::ProcessEventIfMatches(const wxEventTableEntryBase& entry,
1213 wxEvtHandler *handler,
1214 wxEvent& event)
1215{
1216 int tableId1 = entry.m_id,
1217 tableId2 = entry.m_lastId;
1218
1219 // match only if the event type is the same and the id is either -1 in
1220 // the event table (meaning "any") or the event id matches the id
1221 // specified in the event table either exactly or by falling into
1222 // range between first and last
1a18887b
WS
1223 if ((tableId1 == wxID_ANY) ||
1224 (tableId2 == wxID_ANY && tableId1 == event.GetId()) ||
1225 (tableId2 != wxID_ANY &&
1c624631
VZ
1226 (event.GetId() >= tableId1 && event.GetId() <= tableId2)))
1227 {
1228 event.Skip(false);
1229 event.m_callbackUserData = entry.m_callbackUserData;
1230
1231#if wxUSE_EXCEPTIONS
1232 if ( wxTheApp )
1233 {
1234 // call the handler via wxApp method which allows the user to catch
1235 // any exceptions which may be thrown by any handler in the program
1236 // in one place
1237 wxTheApp->HandleEvent(handler, (wxEventFunction)entry.m_fn, event);
1238 }
1239 else
8bd2a804 1240#endif // wxUSE_EXCEPTIONS
1c624631
VZ
1241 {
1242 // no need for an extra virtual function call
1243 (handler->*((wxEventFunction) (entry.m_fn)))(event);
1244 }
1c624631
VZ
1245
1246 if (!event.GetSkipped())
1247 return true;
1248 }
1249
1250 return false;
1251}
c801d85f 1252
4caf847c 1253bool wxEvtHandler::TryParent(wxEvent& event)
c801d85f 1254{
4caf847c 1255 if ( wxTheApp && (this != wxTheApp) )
9154d8cf 1256 {
4caf847c
VZ
1257 // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always
1258 // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be
1259 // processed appropriately via SearchEventTable.
1260 if ( event.GetEventType() != wxEVT_IDLE )
1261 {
1262 if ( wxTheApp->ProcessEvent(event) )
1c624631 1263 return true;
4caf847c 1264 }
9154d8cf
VZ
1265 }
1266
1c624631 1267 return false;
4caf847c 1268}
0b746ba8 1269
4caf847c
VZ
1270bool wxEvtHandler::ProcessEvent(wxEvent& event)
1271{
9154d8cf
VZ
1272 // allow the application to hook into event processing
1273 if ( wxTheApp )
1274 {
1275 int rc = wxTheApp->FilterEvent(event);
1276 if ( rc != -1 )
1277 {
1278 wxASSERT_MSG( rc == 1 || rc == 0,
1279 _T("unexpected wxApp::FilterEvent return value") );
1280
1281 return rc != 0;
1282 }
1283 //else: proceed normally
1284 }
1285
8e193f38 1286 // An event handler can be enabled or disabled
0b746ba8 1287 if ( GetEvtHandlerEnabled() )
c801d85f 1288 {
22c2307c
VZ
1289 // if we have a validator, it has higher priority than our own event
1290 // table
4caf847c 1291 if ( TryValidator(event) )
1c624631 1292 return true;
4caf847c 1293
22c2307c
VZ
1294 // Handle per-instance dynamic event tables first
1295 if ( m_dynamicEvents && SearchDynamicEventTable(event) )
1c624631 1296 return true;
0b746ba8 1297
b5a98acd
VZ
1298 // Then static per-class event tables
1299 if ( GetEventHashTable().HandleEvent(event, this) )
1c624631 1300 return true;
c801d85f
KB
1301 }
1302
0b746ba8
VZ
1303 // Try going down the event handler chain
1304 if ( GetNextHandler() )
c801d85f 1305 {
21dffed2
VZ
1306 // notice that we shouldn't let the parent have the event even if the
1307 // next handler does not process it because it will have already passed
1308 // it to the parent in this case
1309 return GetNextHandler()->ProcessEvent(event);
c801d85f 1310 }
c801d85f 1311
22c2307c
VZ
1312 // Finally propagate the event upwards the window chain and/or to the
1313 // application object as necessary
4caf847c 1314 return TryParent(event);
c801d85f
KB
1315}
1316
b5a98acd 1317
c801d85f
KB
1318bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
1319{
1c624631 1320 const wxEventType eventType = event.GetEventType();
68662769 1321 for ( int i = 0; table.entries[i].m_fn != 0; i++ )
c801d85f 1322 {
68662769 1323 const wxEventTableEntry& entry = table.entries[i];
68662769 1324 if ( eventType == entry.m_eventType )
0b746ba8 1325 {
1c624631
VZ
1326 if ( ProcessEventIfMatches(entry, this, event) )
1327 return true;
0b746ba8 1328 }
c801d85f 1329 }
68662769 1330
1c624631 1331 return false;
c801d85f 1332}
97d7bfb8 1333
debe6624 1334void wxEvtHandler::Connect( int id, int lastId,
77d4384e 1335 int eventType,
0b746ba8 1336 wxObjectEventFunction func,
65b17727
JS
1337 wxObject *userData,
1338 wxEvtHandler* eventSink )
fe71f65c 1339{
cbee8f8d 1340#if WXWIN_COMPATIBILITY_EVENT_TYPES
2e4df4bf 1341 wxEventTableEntry *entry = new wxEventTableEntry;
cbee8f8d
VZ
1342 entry->m_eventType = eventType;
1343 entry->m_id = id;
1344 entry->m_lastId = lastId;
1345 entry->m_fn = func;
1346 entry->m_callbackUserData = userData;
1347#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
0b5eceb6 1348 wxDynamicEventTableEntry *entry =
65b17727 1349 new wxDynamicEventTableEntry(eventType, id, lastId, func, userData, eventSink);
cbee8f8d 1350#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
0b746ba8
VZ
1351
1352 if (!m_dynamicEvents)
1353 m_dynamicEvents = new wxList;
1354
92309201
RD
1355 // Insert at the front of the list so most recent additions are found first
1356 m_dynamicEvents->Insert( (wxObject*) entry );
fe71f65c 1357}
97d7bfb8
RR
1358
1359bool wxEvtHandler::Disconnect( int id, int lastId, wxEventType eventType,
1360 wxObjectEventFunction func,
65b17727
JS
1361 wxObject *userData,
1362 wxEvtHandler* eventSink )
97d7bfb8
RR
1363{
1364 if (!m_dynamicEvents)
1c624631 1365 return false;
cfe17b74 1366
df5168c4 1367 wxList::compatibility_iterator node = m_dynamicEvents->GetFirst();
97d7bfb8
RR
1368 while (node)
1369 {
2e4df4bf 1370#if WXWIN_COMPATIBILITY_EVENT_TYPES
b1d4dd7a 1371 wxEventTableEntry *entry = (wxEventTableEntry*)node->GetData();
2e4df4bf 1372#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
b1d4dd7a 1373 wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
2e4df4bf
VZ
1374#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
1375
97d7bfb8 1376 if ((entry->m_id == id) &&
1a18887b 1377 ((entry->m_lastId == lastId) || (lastId == wxID_ANY)) &&
97d7bfb8
RR
1378 ((entry->m_eventType == eventType) || (eventType == wxEVT_NULL)) &&
1379 ((entry->m_fn == func) || (func == (wxObjectEventFunction)NULL)) &&
65b17727 1380 ((entry->m_eventSink == eventSink) || (eventSink == (wxEvtHandler*)NULL)) &&
97d7bfb8
RR
1381 ((entry->m_callbackUserData == userData) || (userData == (wxObject*)NULL)))
1382 {
2e4df4bf
VZ
1383 if (entry->m_callbackUserData)
1384 delete entry->m_callbackUserData;
df5168c4 1385 m_dynamicEvents->Erase( node );
97d7bfb8 1386 delete entry;
1c624631 1387 return true;
97d7bfb8 1388 }
b1d4dd7a 1389 node = node->GetNext();
97d7bfb8 1390 }
1c624631 1391 return false;
97d7bfb8 1392}
fe71f65c
RR
1393
1394bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
1395{
1c624631 1396 wxCHECK_MSG( m_dynamicEvents, false,
223d09f6 1397 wxT("caller should check that we have dynamic events") );
0b746ba8 1398
df5168c4 1399 wxList::compatibility_iterator node = m_dynamicEvents->GetFirst();
0b746ba8 1400 while (node)
fe71f65c 1401 {
2e4df4bf 1402#if WXWIN_COMPATIBILITY_EVENT_TYPES
1c624631 1403 wxEventTableEntry *entry = (wxEventTableEntry*)node->GetData();
2e4df4bf 1404#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
1c624631 1405 wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
2e4df4bf 1406#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
0b746ba8 1407
7fce89b9
VZ
1408 // get next node before (maybe) calling the event handler as it could
1409 // call Disconnect() invalidating the current node
1410 node = node->GetNext();
1411
ab1931f9 1412 if ((event.GetEventType() == entry->m_eventType) && (entry->m_fn != 0))
0b746ba8 1413 {
1c624631 1414 wxEvtHandler *handler =
65b17727 1415#if !WXWIN_COMPATIBILITY_EVENT_TYPES
1c624631
VZ
1416 entry->m_eventSink ? entry->m_eventSink
1417 :
b5a98acd 1418#endif
1c624631 1419 this;
0b746ba8 1420
1c624631
VZ
1421 if ( ProcessEventIfMatches(*entry, handler, event) )
1422 {
1423 return true;
0b746ba8
VZ
1424 }
1425 }
7b678698 1426 }
1c624631
VZ
1427
1428 return false;
4115960d 1429}
fe71f65c 1430
b88c44e7
RD
1431void wxEvtHandler::DoSetClientObject( wxClientData *data )
1432{
1433 wxASSERT_MSG( m_clientDataType != wxClientData_Void,
1434 wxT("can't have both object and void client data") );
1435
1436 if ( m_clientObject )
1437 delete m_clientObject;
1438
1439 m_clientObject = data;
1440 m_clientDataType = wxClientData_Object;
1441}
1442
1443wxClientData *wxEvtHandler::DoGetClientObject() const
1444{
1445 // it's not an error to call GetClientObject() on a window which doesn't
1446 // have client data at all - NULL will be returned
1447 wxASSERT_MSG( m_clientDataType != wxClientData_Void,
1448 wxT("this window doesn't have object client data") );
1449
1450 return m_clientObject;
1451}
1452
1453void wxEvtHandler::DoSetClientData( void *data )
1454{
1455 wxASSERT_MSG( m_clientDataType != wxClientData_Object,
1456 wxT("can't have both object and void client data") );
1457
1458 m_clientData = data;
1459 m_clientDataType = wxClientData_Void;
1460}
1461
1462void *wxEvtHandler::DoGetClientData() const
1463{
1464 // it's not an error to call GetClientData() on a window which doesn't have
1465 // client data at all - NULL will be returned
1466 wxASSERT_MSG( m_clientDataType != wxClientData_Object,
1467 wxT("this window doesn't have void client data") );
1468
1469 return m_clientData;
1470}
1471
4caf847c
VZ
1472#endif // wxUSE_BASE
1473
e90c1d2a
VZ
1474#if wxUSE_GUI
1475
e702ff0f
JS
1476// Find a window with the focus, that is also a descendant of the given window.
1477// This is used to determine the window to initially send commands to.
1478wxWindow* wxFindFocusDescendant(wxWindow* ancestor)
1479{
1480 // Process events starting with the window with the focus, if any.
1481 wxWindow* focusWin = wxWindow::FindFocus();
1482 wxWindow* win = focusWin;
1483
1484 // Check if this is a descendant of this frame.
1485 // If not, win will be set to NULL.
1486 while (win)
1487 {
1488 if (win == ancestor)
1489 break;
1490 else
1491 win = win->GetParent();
1492 }
1493 if (win == (wxWindow*) NULL)
1494 focusWin = (wxWindow*) NULL;
1495
1496 return focusWin;
1497}
1498
c4fa5aa7
VZ
1499// ----------------------------------------------------------------------------
1500// wxEventBlocker
1501// ----------------------------------------------------------------------------
1502
1503wxEventBlocker::wxEventBlocker(wxWindow *win, wxEventType type)
1504{
1505 wxCHECK_RET(win, wxT("Null window given to wxEventBlocker"));
1506
1507 m_window = win;
1508
1509 Block(type);
1510 m_window->PushEventHandler(this);
1511}
1512
1513wxEventBlocker::~wxEventBlocker()
1514{
1515 wxEvtHandler *popped = m_window->PopEventHandler(false);
aa767a45 1516 wxCHECK_RET(popped == this,
c4fa5aa7
VZ
1517 wxT("Don't push other event handlers into a window managed by wxEventBlocker!"));
1518}
1519
1520bool wxEventBlocker::ProcessEvent(wxEvent& event)
1521{
1522 // should this event be blocked?
1523 for ( size_t i = 0; i < m_eventsToBlock.size(); i++ )
1524 {
1525 wxEventType t = (wxEventType)m_eventsToBlock[i];
1526 if ( t == wxEVT_ANY || t == event.GetEventType() )
1527 return true; // yes, it should: mark this event as processed
1528 }
1529
1530 return false;
1531}
1532
e90c1d2a 1533#endif // wxUSE_GUI