Implemented wxEventLoop for wxMotif, and used it in wxDialog::ShowModal,
wxWindow::DoPopupMenu and for the application main loop. Implemented wxWakeUpIdle. Fixed crash when a popup menu entry is used to close/destroy the parent window of the menu. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19078 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -584,6 +584,7 @@ dcclient.cpp Motif
|
|||||||
dcmemory.cpp Motif
|
dcmemory.cpp Motif
|
||||||
dcscreen.cpp Motif
|
dcscreen.cpp Motif
|
||||||
dialog.cpp Motif
|
dialog.cpp Motif
|
||||||
|
evtloop.cpp Motif
|
||||||
filedlg.cpp Motif
|
filedlg.cpp Motif
|
||||||
font.cpp Motif
|
font.cpp Motif
|
||||||
frame.cpp Motif
|
frame.cpp Motif
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
// headers
|
// headers
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "wx/gdicmn.h"
|
|
||||||
#include "wx/event.h"
|
#include "wx/event.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -32,6 +31,7 @@ class WXDLLEXPORT wxWindow;
|
|||||||
class WXDLLEXPORT wxApp;
|
class WXDLLEXPORT wxApp;
|
||||||
class WXDLLEXPORT wxKeyEvent;
|
class WXDLLEXPORT wxKeyEvent;
|
||||||
class WXDLLEXPORT wxLog;
|
class WXDLLEXPORT wxLog;
|
||||||
|
class WXDLLEXPORT wxEventLoop;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// the wxApp class for Motif - see wxAppBase for more details
|
// the wxApp class for Motif - see wxAppBase for more details
|
||||||
@@ -43,7 +43,7 @@ class WXDLLEXPORT wxApp : public wxAppBase
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
wxApp();
|
wxApp();
|
||||||
~wxApp() {}
|
virtual ~wxApp();
|
||||||
|
|
||||||
// override base class (pure) virtuals
|
// override base class (pure) virtuals
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
@@ -71,20 +71,6 @@ public:
|
|||||||
// Returns TRUE if more idle time is requested.
|
// Returns TRUE if more idle time is requested.
|
||||||
bool SendIdleEvents(wxWindow* win);
|
bool SendIdleEvents(wxWindow* win);
|
||||||
|
|
||||||
// Motif implementation.
|
|
||||||
|
|
||||||
// Processes an X event.
|
|
||||||
virtual void ProcessXEvent(WXEvent* event);
|
|
||||||
|
|
||||||
// Returns TRUE if an accelerator has been processed
|
|
||||||
virtual bool CheckForAccelerator(WXEvent* event);
|
|
||||||
|
|
||||||
// Returns TRUE if a key down event has been processed
|
|
||||||
virtual bool CheckForKeyDown(WXEvent* event);
|
|
||||||
|
|
||||||
// Returns TRUE if a key up event has been processed
|
|
||||||
virtual bool CheckForKeyUp(WXEvent* event);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_showOnInit;
|
bool m_showOnInit;
|
||||||
|
|
||||||
@@ -105,12 +91,11 @@ public:
|
|||||||
// This handler is called when a property change event occurs
|
// This handler is called when a property change event occurs
|
||||||
virtual void HandlePropertyChange(WXEvent *event);
|
virtual void HandlePropertyChange(WXEvent *event);
|
||||||
|
|
||||||
public:
|
private:
|
||||||
static long sm_lastMessageTime;
|
static long sm_lastMessageTime;
|
||||||
int m_nCmdShow;
|
int m_nCmdShow;
|
||||||
|
|
||||||
protected:
|
wxEventLoop* m_eventLoop;
|
||||||
bool m_keepGoing;
|
|
||||||
|
|
||||||
// Motif-specific
|
// Motif-specific
|
||||||
WXAppContext m_appContext;
|
WXAppContext m_appContext;
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
WXDLLEXPORT_DATA(extern const char*) wxDialogNameStr;
|
WXDLLEXPORT_DATA(extern const char*) wxDialogNameStr;
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxEventLoop;
|
||||||
|
|
||||||
// Dialog boxes
|
// Dialog boxes
|
||||||
class WXDLLEXPORT wxDialog : public wxDialogBase
|
class WXDLLEXPORT wxDialog : public wxDialogBase
|
||||||
{
|
{
|
||||||
@@ -102,6 +104,7 @@ private:
|
|||||||
|
|
||||||
//// Motif-specific
|
//// Motif-specific
|
||||||
bool m_modalShowing;
|
bool m_modalShowing;
|
||||||
|
wxEventLoop* m_eventLoop;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void DoSetSize(int x, int y,
|
virtual void DoSetSize(int x, int y,
|
||||||
|
@@ -93,7 +93,8 @@ public:
|
|||||||
WXWidget GetHandle() const { return m_menuWidget; }
|
WXWidget GetHandle() const { return m_menuWidget; }
|
||||||
|
|
||||||
bool IsTearOff() const { return (m_style & wxMENU_TEAROFF) != 0; }
|
bool IsTearOff() const { return (m_style & wxMENU_TEAROFF) != 0; }
|
||||||
|
|
||||||
|
void DestroyWidgetAndDetach();
|
||||||
public:
|
public:
|
||||||
// Motif-specific data
|
// Motif-specific data
|
||||||
int m_numColumns;
|
int m_numColumns;
|
||||||
|
@@ -25,10 +25,12 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// All widgets should have this as their resize proc.
|
// All widgets should have this as their resize proc.
|
||||||
extern void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args);
|
extern void wxWidgetResizeProc(Widget w, XConfigureEvent *event,
|
||||||
|
String args[], int *num_args);
|
||||||
|
|
||||||
// For repainting arbitrary windows
|
// For repainting arbitrary windows
|
||||||
void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *);
|
void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data),
|
||||||
|
XEvent *event, char *);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// we maintain a hash table which contains the mapping from Widget to wxWindow
|
// we maintain a hash table which contains the mapping from Widget to wxWindow
|
||||||
@@ -51,11 +53,17 @@ extern XmString wxFindAcceleratorText (const char *s);
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// TranslateXXXEvent() functions - translate Motif event to wxWindow one
|
// TranslateXXXEvent() functions - translate Motif event to wxWindow one
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
extern bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent);
|
|
||||||
extern bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent);
|
|
||||||
|
|
||||||
extern void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour);
|
extern bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win,
|
||||||
extern void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour = FALSE);
|
Widget widget, XEvent *xevent);
|
||||||
|
extern bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win,
|
||||||
|
Widget widget, XEvent *xevent);
|
||||||
|
|
||||||
|
extern void wxDoChangeForegroundColour(WXWidget widget,
|
||||||
|
wxColour& foregroundColour);
|
||||||
|
extern void wxDoChangeBackgroundColour(WXWidget widget,
|
||||||
|
wxColour& backgroundColour,
|
||||||
|
bool changeArmColour = FALSE);
|
||||||
|
|
||||||
#define wxNO_COLORS 0x00
|
#define wxNO_COLORS 0x00
|
||||||
#define wxBACK_COLORS 0x01
|
#define wxBACK_COLORS 0x01
|
||||||
@@ -78,6 +86,11 @@ extern XColor itemColors[5] ;
|
|||||||
class wxXmString
|
class wxXmString
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
wxXmString(const char* str)
|
||||||
|
{
|
||||||
|
m_string = XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
wxXmString(const wxString& str)
|
wxXmString(const wxString& str)
|
||||||
{
|
{
|
||||||
m_string = XmStringCreateLtoR((char *)str.c_str(),
|
m_string = XmStringCreateLtoR((char *)str.c_str(),
|
||||||
@@ -94,6 +107,15 @@ private:
|
|||||||
XmString m_string;
|
XmString m_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// executes one main loop iteration (implemented in src/motif/evtloop.cpp)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxEventLoop;
|
||||||
|
|
||||||
|
// returns true if the loop should be exited
|
||||||
|
bool wxDoEventLoopIteration( wxEventLoop& evtLoop );
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// macros to avoid casting WXFOO to Foo all the time
|
// macros to avoid casting WXFOO to Foo all the time
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "wx/memory.h"
|
#include "wx/memory.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/intl.h"
|
#include "wx/intl.h"
|
||||||
|
#include "wx/evtloop.h"
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
#include "wx/thread.h"
|
#include "wx/thread.h"
|
||||||
@@ -61,6 +62,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern wxList wxPendingDelete;
|
extern wxList wxPendingDelete;
|
||||||
|
extern bool wxAddIdleCallback();
|
||||||
|
|
||||||
wxApp *wxTheApp = NULL;
|
wxApp *wxTheApp = NULL;
|
||||||
|
|
||||||
@@ -267,6 +269,7 @@ wxApp::wxApp()
|
|||||||
argc = 0;
|
argc = 0;
|
||||||
argv = NULL;
|
argv = NULL;
|
||||||
|
|
||||||
|
m_eventLoop = new wxEventLoop;
|
||||||
m_mainColormap = (WXColormap) NULL;
|
m_mainColormap = (WXColormap) NULL;
|
||||||
m_appContext = (WXAppContext) NULL;
|
m_appContext = (WXAppContext) NULL;
|
||||||
m_topLevelWidget = (WXWidget) NULL;
|
m_topLevelWidget = (WXWidget) NULL;
|
||||||
@@ -274,6 +277,11 @@ wxApp::wxApp()
|
|||||||
m_initialDisplay = (WXDisplay*) 0;
|
m_initialDisplay = (WXDisplay*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxApp::~wxApp()
|
||||||
|
{
|
||||||
|
delete m_eventLoop;
|
||||||
|
}
|
||||||
|
|
||||||
bool wxApp::Initialized()
|
bool wxApp::Initialized()
|
||||||
{
|
{
|
||||||
if (GetTopWindow())
|
if (GetTopWindow())
|
||||||
@@ -284,8 +292,6 @@ bool wxApp::Initialized()
|
|||||||
|
|
||||||
int wxApp::MainLoop()
|
int wxApp::MainLoop()
|
||||||
{
|
{
|
||||||
m_keepGoing = TRUE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sit around forever waiting to process X-events. Property Change
|
* Sit around forever waiting to process X-events. Property Change
|
||||||
* event are handled special, because they have to refer to
|
* event are handled special, because they have to refer to
|
||||||
@@ -297,129 +303,23 @@ int wxApp::MainLoop()
|
|||||||
XDefaultRootWindow(XtDisplay((Widget) wxTheApp->GetTopLevelWidget())),
|
XDefaultRootWindow(XtDisplay((Widget) wxTheApp->GetTopLevelWidget())),
|
||||||
PropertyChangeMask);
|
PropertyChangeMask);
|
||||||
|
|
||||||
XEvent event;
|
m_eventLoop->Run();
|
||||||
|
|
||||||
// Use this flag to allow breaking the loop via wxApp::ExitMainLoop()
|
|
||||||
while (m_keepGoing)
|
|
||||||
{
|
|
||||||
XtAppNextEvent( (XtAppContext) wxTheApp->GetAppContext(), &event);
|
|
||||||
|
|
||||||
ProcessXEvent((WXEvent*) & event);
|
|
||||||
|
|
||||||
if (XtAppPending( (XtAppContext) wxTheApp->GetAppContext() ) == 0)
|
|
||||||
{
|
|
||||||
if (!ProcessIdle())
|
|
||||||
{
|
|
||||||
#if wxUSE_THREADS
|
|
||||||
// leave the main loop to give other threads a chance to
|
|
||||||
// perform their GUI work
|
|
||||||
wxMutexGuiLeave();
|
|
||||||
wxUsleep(20);
|
|
||||||
wxMutexGuiEnter();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes an X event.
|
// Processes an idle event.
|
||||||
void wxApp::ProcessXEvent(WXEvent* _event)
|
|
||||||
{
|
|
||||||
XEvent* event = (XEvent*) _event;
|
|
||||||
|
|
||||||
if (event->type == KeyPress)
|
|
||||||
{
|
|
||||||
#if 0 // def __WXDEBUG__
|
|
||||||
Widget widget = XtWindowToWidget(event->xany.display, event->xany.window);
|
|
||||||
wxLogDebug("Got key press event for 0x%08x (parent = 0x%08x)",
|
|
||||||
widget, XtParent(widget));
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
if (CheckForAccelerator(_event))
|
|
||||||
{
|
|
||||||
// Do nothing! We intercepted and processed the event as an
|
|
||||||
// accelerator.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
// It seemed before that this hack was redundant and
|
|
||||||
// key down events were being generated by wxCanvasInputEvent.
|
|
||||||
// But no longer - why ???
|
|
||||||
//
|
|
||||||
else if (CheckForKeyDown(_event))
|
|
||||||
{
|
|
||||||
// We intercepted and processed the key down event
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XtDispatchEvent(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == KeyRelease)
|
|
||||||
{
|
|
||||||
// TODO: work out why we still need this ! -michael
|
|
||||||
//
|
|
||||||
if (CheckForKeyUp(_event))
|
|
||||||
{
|
|
||||||
// We intercepted and processed the key up event
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XtDispatchEvent(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type == PropertyNotify)
|
|
||||||
{
|
|
||||||
HandlePropertyChange(_event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (event->type == ResizeRequest)
|
|
||||||
{
|
|
||||||
/* Terry Gitnick <terryg@scientech.com> - 1/21/98
|
|
||||||
* If resize event, don't resize until the last resize event for this
|
|
||||||
* window is recieved. Prevents flicker as windows are resized.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Display *disp = XtDisplay((Widget) wxTheApp->GetTopLevelWidget());
|
|
||||||
Window win = event->xany.window;
|
|
||||||
XEvent report;
|
|
||||||
|
|
||||||
// to avoid flicker
|
|
||||||
report = * event;
|
|
||||||
while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report));
|
|
||||||
|
|
||||||
// TODO: when implementing refresh optimization, we can use
|
|
||||||
// XtAddExposureToRegion to expand the window's paint region.
|
|
||||||
|
|
||||||
XtDispatchEvent(event);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XtDispatchEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns TRUE if more time is needed.
|
// Returns TRUE if more time is needed.
|
||||||
bool wxApp::ProcessIdle()
|
bool wxApp::ProcessIdle()
|
||||||
{
|
{
|
||||||
wxIdleEvent event;
|
wxIdleEvent event;
|
||||||
event.SetEventObject(this);
|
|
||||||
ProcessEvent(event);
|
|
||||||
|
|
||||||
return event.MoreRequested();
|
return ProcessEvent(event) && event.MoreRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxApp::ExitMainLoop()
|
void wxApp::ExitMainLoop()
|
||||||
{
|
{
|
||||||
m_keepGoing = FALSE;
|
m_eventLoop->Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is a message/event pending?
|
// Is a message/event pending?
|
||||||
@@ -435,11 +335,7 @@ bool wxApp::Pending()
|
|||||||
// Dispatch a message.
|
// Dispatch a message.
|
||||||
void wxApp::Dispatch()
|
void wxApp::Dispatch()
|
||||||
{
|
{
|
||||||
// XtAppProcessEvent( (XtAppContext) wxTheApp->GetAppContext(), XtIMAll);
|
m_eventLoop->Dispatch();
|
||||||
|
|
||||||
XEvent event;
|
|
||||||
XtAppNextEvent((XtAppContext) GetAppContext(), &event);
|
|
||||||
ProcessXEvent((WXEvent*) & event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be redefined in a derived class for
|
// This should be redefined in a derived class for
|
||||||
@@ -489,13 +385,6 @@ void wxApp::OnIdle(wxIdleEvent& event)
|
|||||||
inOnIdle = FALSE;
|
inOnIdle = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWakeUpIdle()
|
|
||||||
{
|
|
||||||
// **** please implement me! ****
|
|
||||||
// Wake up the idle handler processor, even if it is in another thread...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Send idle event to all top-level windows
|
// Send idle event to all top-level windows
|
||||||
bool wxApp::SendIdleEvents()
|
bool wxApp::SendIdleEvents()
|
||||||
{
|
{
|
||||||
@@ -539,7 +428,7 @@ bool wxApp::SendIdleEvents(wxWindow* win)
|
|||||||
|
|
||||||
void wxApp::DeletePendingObjects()
|
void wxApp::DeletePendingObjects()
|
||||||
{
|
{
|
||||||
wxNode *node = wxPendingDelete.GetFirst();
|
wxList::Node *node = wxPendingDelete.GetFirst();
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
wxObject *obj = node->GetData();
|
wxObject *obj = node->GetData();
|
||||||
@@ -610,6 +499,8 @@ bool wxApp::OnInitGui()
|
|||||||
GetMainColormap(dpy);
|
GetMainColormap(dpy);
|
||||||
m_maxRequestSize = XMaxRequestSize((Display*) dpy);
|
m_maxRequestSize = XMaxRequestSize((Display*) dpy);
|
||||||
|
|
||||||
|
wxAddIdleCallback();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,91 +520,6 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display)
|
|||||||
return (WXColormap) c;
|
return (WXColormap) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns TRUE if an accelerator has been processed
|
|
||||||
bool wxApp::CheckForAccelerator(WXEvent* event)
|
|
||||||
{
|
|
||||||
XEvent* xEvent = (XEvent*) event;
|
|
||||||
if (xEvent->xany.type == KeyPress)
|
|
||||||
{
|
|
||||||
// Find a wxWindow for this window
|
|
||||||
// TODO: should get display for the window, not the current display
|
|
||||||
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(), xEvent->xany.window);
|
|
||||||
wxWindow* win = NULL;
|
|
||||||
|
|
||||||
// Find the first wxWindow that corresponds to this event window
|
|
||||||
while (widget && !(win = wxGetWindowFromTable(widget)))
|
|
||||||
widget = XtParent(widget);
|
|
||||||
|
|
||||||
if (!widget || !win)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
wxKeyEvent keyEvent(wxEVT_CHAR);
|
|
||||||
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, xEvent);
|
|
||||||
|
|
||||||
// Now we have a wxKeyEvent and we have a wxWindow.
|
|
||||||
// Go up the hierarchy until we find a matching accelerator,
|
|
||||||
// or we get to the top.
|
|
||||||
while (win)
|
|
||||||
{
|
|
||||||
if (win->ProcessAccelerator(keyEvent))
|
|
||||||
return TRUE;
|
|
||||||
win = win->GetParent();
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxApp::CheckForKeyDown(WXEvent* event)
|
|
||||||
{
|
|
||||||
XEvent* xEvent = (XEvent*) event;
|
|
||||||
if (xEvent->xany.type == KeyPress)
|
|
||||||
{
|
|
||||||
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
|
|
||||||
xEvent->xany.window);
|
|
||||||
wxWindow* win = NULL;
|
|
||||||
|
|
||||||
// Find the first wxWindow that corresponds to this event window
|
|
||||||
while (widget && !(win = wxGetWindowFromTable(widget)))
|
|
||||||
widget = XtParent(widget);
|
|
||||||
|
|
||||||
if (!widget || !win)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
|
|
||||||
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, xEvent);
|
|
||||||
|
|
||||||
return win->ProcessEvent( keyEvent );
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wxApp::CheckForKeyUp(WXEvent* event)
|
|
||||||
{
|
|
||||||
XEvent* xEvent = (XEvent*) event;
|
|
||||||
if (xEvent->xany.type == KeyRelease)
|
|
||||||
{
|
|
||||||
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
|
|
||||||
xEvent->xany.window);
|
|
||||||
wxWindow* win = NULL;
|
|
||||||
|
|
||||||
// Find the first wxWindow that corresponds to this event window
|
|
||||||
while (widget && !(win = wxGetWindowFromTable(widget)))
|
|
||||||
widget = XtParent(widget);
|
|
||||||
|
|
||||||
if (!widget || !win)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
wxKeyEvent keyEvent(wxEVT_KEY_UP);
|
|
||||||
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, xEvent);
|
|
||||||
|
|
||||||
return win->ProcessEvent( keyEvent );
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxExit()
|
void wxExit()
|
||||||
{
|
{
|
||||||
int retValue = 0;
|
int retValue = 0;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include "wx/utils.h"
|
#include "wx/utils.h"
|
||||||
#include "wx/app.h"
|
#include "wx/app.h"
|
||||||
#include "wx/settings.h"
|
#include "wx/settings.h"
|
||||||
|
#include "wx/evtloop.h"
|
||||||
|
|
||||||
#ifdef __VMS__
|
#ifdef __VMS__
|
||||||
#pragma message disable nosimpint
|
#pragma message disable nosimpint
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
// A stack of modal_showing flags, since we can't rely
|
// A stack of modal_showing flags, since we can't rely
|
||||||
// on accessing wxDialog::m_modalShowing within
|
// on accessing wxDialog::m_modalShowing within
|
||||||
// wxDialog::Show in case a callback has deleted the wxDialog.
|
// wxDialog::Show in case a callback has deleted the wxDialog.
|
||||||
static wxList wxModalShowingStack;
|
// static wxList wxModalShowingStack;
|
||||||
|
|
||||||
// Lists to keep track of windows, so we can disable/enable them
|
// Lists to keep track of windows, so we can disable/enable them
|
||||||
// for modal dialogs
|
// for modal dialogs
|
||||||
@@ -81,6 +82,7 @@ END_EVENT_TABLE()
|
|||||||
wxDialog::wxDialog()
|
wxDialog::wxDialog()
|
||||||
{
|
{
|
||||||
m_modalShowing = FALSE;
|
m_modalShowing = FALSE;
|
||||||
|
m_eventLoop = NULL;
|
||||||
m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
|
m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +100,7 @@ bool wxDialog::Create(wxWindow *parent, wxWindowID id,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
m_modalShowing = FALSE;
|
m_modalShowing = FALSE;
|
||||||
|
m_eventLoop = NULL;
|
||||||
|
|
||||||
m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
|
m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
|
||||||
m_foregroundColour = *wxBLACK;
|
m_foregroundColour = *wxBLACK;
|
||||||
@@ -204,6 +207,7 @@ void wxDialog::SetModal(bool flag)
|
|||||||
wxDialog::~wxDialog()
|
wxDialog::~wxDialog()
|
||||||
{
|
{
|
||||||
m_isBeingDeleted = TRUE;
|
m_isBeingDeleted = TRUE;
|
||||||
|
delete m_eventLoop;
|
||||||
|
|
||||||
if (m_mainWidget)
|
if (m_mainWidget)
|
||||||
{
|
{
|
||||||
@@ -312,52 +316,24 @@ int wxDialog::ShowModal()
|
|||||||
|
|
||||||
if (m_modalShowing)
|
if (m_modalShowing)
|
||||||
return 0;
|
return 0;
|
||||||
|
m_eventLoop = new wxEventLoop;
|
||||||
wxModalShowingStack.Insert((wxObject *)TRUE);
|
|
||||||
|
|
||||||
m_modalShowing = TRUE;
|
m_modalShowing = TRUE;
|
||||||
XtAddGrab((Widget) m_mainWidget, TRUE, FALSE);
|
XtAddGrab((Widget) m_mainWidget, TRUE, FALSE);
|
||||||
|
|
||||||
XEvent event;
|
m_eventLoop->Run();
|
||||||
|
|
||||||
// Loop until we signal that the dialog should be closed
|
|
||||||
while ((wxModalShowingStack.Number() > 0) && ((int)(wxModalShowingStack.First()->Data()) != 0))
|
|
||||||
{
|
|
||||||
// XtAppProcessEvent((XtAppContext) wxTheApp->GetAppContext(), XtIMAll);
|
|
||||||
|
|
||||||
XtAppNextEvent((XtAppContext) wxTheApp->GetAppContext(), &event);
|
|
||||||
wxTheApp->ProcessXEvent((WXEvent*) &event);
|
|
||||||
|
|
||||||
if (XtAppPending( (XtAppContext) wxTheApp->GetAppContext() ) == 0)
|
|
||||||
{
|
|
||||||
if (!wxTheApp->ProcessIdle())
|
|
||||||
{
|
|
||||||
#if wxUSE_THREADS
|
|
||||||
// leave the main loop to give other threads a chance to
|
|
||||||
// perform their GUI work
|
|
||||||
wxMutexGuiLeave();
|
|
||||||
wxUsleep(20);
|
|
||||||
wxMutexGuiEnter();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove modal dialog flag from stack
|
|
||||||
wxNode *node = wxModalShowingStack.First();
|
|
||||||
if (node)
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
// Now process all events in case they get sent to a destroyed dialog
|
// Now process all events in case they get sent to a destroyed dialog
|
||||||
XSync(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()), FALSE);
|
XSync(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()), FALSE);
|
||||||
while (XtAppPending((XtAppContext) wxTheApp->GetAppContext()))
|
while (m_eventLoop->Pending())
|
||||||
{
|
{
|
||||||
XFlush(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()));
|
XFlush(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()));
|
||||||
XtAppNextEvent((XtAppContext) wxTheApp->GetAppContext(), &event);
|
m_eventLoop->Dispatch();
|
||||||
|
|
||||||
wxTheApp->ProcessXEvent((WXEvent*) &event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete m_eventLoop;
|
||||||
|
m_eventLoop = NULL;
|
||||||
|
|
||||||
// TODO: is it safe to call this, if the dialog may have been deleted
|
// TODO: is it safe to call this, if the dialog may have been deleted
|
||||||
// by now? Probably only if we're using delayed deletion of dialogs.
|
// by now? Probably only if we're using delayed deletion of dialogs.
|
||||||
return GetReturnCode();
|
return GetReturnCode();
|
||||||
@@ -376,10 +352,7 @@ void wxDialog::EndModal(int retCode)
|
|||||||
Show(FALSE);
|
Show(FALSE);
|
||||||
|
|
||||||
m_modalShowing = FALSE;
|
m_modalShowing = FALSE;
|
||||||
|
m_eventLoop->Exit();
|
||||||
wxNode *node = wxModalShowingStack.First();
|
|
||||||
if (node)
|
|
||||||
node->SetData((wxObject *)FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard buttons
|
// Standard buttons
|
||||||
|
467
src/motif/evtloop.cpp
Normal file
467
src/motif/evtloop.cpp
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: motif/evtloop.cpp
|
||||||
|
// Purpose: implements wxEventLoop for Motif
|
||||||
|
// Author: Mattia Barbon
|
||||||
|
// Modified by:
|
||||||
|
// Created: 01.11.02
|
||||||
|
// RCS-ID: $Id$
|
||||||
|
// Copyright: (c) 2002 Mattia Barbon
|
||||||
|
// License: wxWindows license
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// declarations
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// headers
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma implementation "evtloop.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __VMS
|
||||||
|
#define XtParent XTPARENT
|
||||||
|
#define XtDisplay XTDISPLAY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#ifndef WX_PRECOMP
|
||||||
|
#endif //WX_PRECOMP
|
||||||
|
|
||||||
|
#include "wx/evtloop.h"
|
||||||
|
#include "wx/event.h"
|
||||||
|
#include "wx/app.h"
|
||||||
|
|
||||||
|
#ifdef __VMS__
|
||||||
|
#pragma message disable nosimpint
|
||||||
|
#endif
|
||||||
|
#include <Xm/Xm.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#ifdef __VMS__
|
||||||
|
#pragma message enable nosimpint
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wx/motif/private.h"
|
||||||
|
|
||||||
|
static bool CheckForKeyUp(XEvent* event);
|
||||||
|
static bool CheckForKeyDown(XEvent* event);
|
||||||
|
static bool CheckForAccelerator(XEvent* event);
|
||||||
|
static void ProcessXEvent(XEvent* event);
|
||||||
|
static void wxBreakDispatch();
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxEventLoopImpl
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxEventLoopImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// ctor
|
||||||
|
wxEventLoopImpl() { SetExitCode(0); }
|
||||||
|
|
||||||
|
// set/get the exit code
|
||||||
|
void SetExitCode(int exitcode) { m_exitcode = exitcode; }
|
||||||
|
int GetExitCode() const { return m_exitcode; }
|
||||||
|
|
||||||
|
bool SendIdleMessage();
|
||||||
|
bool GetKeepGoing() const { return m_keepGoing; }
|
||||||
|
void SetKeepGoing(bool keepGoing) { m_keepGoing = keepGoing; }
|
||||||
|
private:
|
||||||
|
// the exit code of the event loop
|
||||||
|
int m_exitcode;
|
||||||
|
bool m_keepGoing;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxEventLoopImpl idle event processing
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static bool SendIdleMessage()
|
||||||
|
{
|
||||||
|
wxIdleEvent event;
|
||||||
|
|
||||||
|
return wxTheApp->ProcessEvent(event) && event.MoreRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxEventLoopImpl::SendIdleMessage()
|
||||||
|
{
|
||||||
|
return ::SendIdleMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxEventLoop implementation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxEventLoop running and exiting
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxEventLoop *wxEventLoop::ms_activeLoop = NULL;
|
||||||
|
|
||||||
|
wxEventLoop::~wxEventLoop()
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxEventLoop::IsRunning() const
|
||||||
|
{
|
||||||
|
return m_impl != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wxEventLoop::Run()
|
||||||
|
{
|
||||||
|
// event loops are not recursive, you need to create another loop!
|
||||||
|
wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
|
||||||
|
|
||||||
|
wxEventLoop *oldLoop = ms_activeLoop;
|
||||||
|
ms_activeLoop = this;
|
||||||
|
|
||||||
|
m_impl = new wxEventLoopImpl;
|
||||||
|
m_impl->SetKeepGoing( true );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( !wxDoEventLoopIteration( *this ) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitcode = m_impl->GetExitCode();
|
||||||
|
delete m_impl;
|
||||||
|
m_impl = NULL;
|
||||||
|
|
||||||
|
ms_activeLoop = oldLoop;
|
||||||
|
|
||||||
|
return exitcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxEventLoop::Exit(int rc)
|
||||||
|
{
|
||||||
|
wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
|
||||||
|
|
||||||
|
m_impl->SetExitCode(rc);
|
||||||
|
m_impl->SetKeepGoing( false );
|
||||||
|
|
||||||
|
::wxBreakDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxEventLoop message processing dispatching
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool wxEventLoop::Pending() const
|
||||||
|
{
|
||||||
|
return XtAppPending( (XtAppContext)wxTheApp->GetAppContext() ) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxEventLoop::Dispatch()
|
||||||
|
{
|
||||||
|
XEvent event;
|
||||||
|
XtAppContext context = (XtAppContext)wxTheApp->GetAppContext();
|
||||||
|
|
||||||
|
if( XtAppPeekEvent( context, &event ) != 0 )
|
||||||
|
{
|
||||||
|
XtAppNextEvent( context, &event );
|
||||||
|
ProcessXEvent( &event );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
XtAppProcessEvent( context, XtIMTimer|XtIMAlternateInput|XtIMSignal );
|
||||||
|
|
||||||
|
return m_impl ? m_impl->GetKeepGoing() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Static functions (originally in app.cpp)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ProcessXEvent(XEvent* event)
|
||||||
|
{
|
||||||
|
if (event->type == KeyPress)
|
||||||
|
{
|
||||||
|
if (CheckForAccelerator(event))
|
||||||
|
{
|
||||||
|
// Do nothing! We intercepted and processed the event as an
|
||||||
|
// accelerator.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// It seemed before that this hack was redundant and
|
||||||
|
// key down events were being generated by wxCanvasInputEvent.
|
||||||
|
// But no longer - why ???
|
||||||
|
//
|
||||||
|
else if (CheckForKeyDown(event))
|
||||||
|
{
|
||||||
|
// We intercepted and processed the key down event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XtDispatchEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event->type == KeyRelease)
|
||||||
|
{
|
||||||
|
// TODO: work out why we still need this ! -michael
|
||||||
|
//
|
||||||
|
if (::CheckForKeyUp(event))
|
||||||
|
{
|
||||||
|
// We intercepted and processed the key up event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XtDispatchEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event->type == PropertyNotify)
|
||||||
|
{
|
||||||
|
wxTheApp->HandlePropertyChange(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (event->type == ResizeRequest)
|
||||||
|
{
|
||||||
|
/* Terry Gitnick <terryg@scientech.com> - 1/21/98
|
||||||
|
* If resize event, don't resize until the last resize event for this
|
||||||
|
* window is recieved. Prevents flicker as windows are resized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Display *disp = XtDisplay((Widget) wxTheApp->GetTopLevelWidget());
|
||||||
|
Window win = event->xany.window;
|
||||||
|
XEvent report;
|
||||||
|
|
||||||
|
// to avoid flicker
|
||||||
|
report = * event;
|
||||||
|
while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report));
|
||||||
|
|
||||||
|
// TODO: when implementing refresh optimization, we can use
|
||||||
|
// XtAddExposureToRegion to expand the window's paint region.
|
||||||
|
|
||||||
|
XtDispatchEvent(event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XtDispatchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if an accelerator has been processed
|
||||||
|
bool CheckForAccelerator(XEvent* event)
|
||||||
|
{
|
||||||
|
if (event->xany.type == KeyPress)
|
||||||
|
{
|
||||||
|
// Find a wxWindow for this window
|
||||||
|
// TODO: should get display for the window, not the current display
|
||||||
|
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
|
||||||
|
event->xany.window);
|
||||||
|
wxWindow* win = NULL;
|
||||||
|
|
||||||
|
// Find the first wxWindow that corresponds to this event window
|
||||||
|
while (widget && !(win = wxGetWindowFromTable(widget)))
|
||||||
|
widget = XtParent(widget);
|
||||||
|
|
||||||
|
if (!widget || !win)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxKeyEvent keyEvent(wxEVT_CHAR);
|
||||||
|
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, event);
|
||||||
|
|
||||||
|
// Now we have a wxKeyEvent and we have a wxWindow.
|
||||||
|
// Go up the hierarchy until we find a matching accelerator,
|
||||||
|
// or we get to the top.
|
||||||
|
while (win)
|
||||||
|
{
|
||||||
|
if (win->ProcessAccelerator(keyEvent))
|
||||||
|
return true;
|
||||||
|
win = win->GetParent();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool wxApp::CheckForKeyDown(WXEvent* event) { wxFAIL; return false; }
|
||||||
|
|
||||||
|
bool CheckForKeyDown(XEvent* event)
|
||||||
|
{
|
||||||
|
if (event->xany.type == KeyPress)
|
||||||
|
{
|
||||||
|
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
|
||||||
|
event->xany.window);
|
||||||
|
wxWindow* win = NULL;
|
||||||
|
|
||||||
|
// Find the first wxWindow that corresponds to this event window
|
||||||
|
while (widget && !(win = wxGetWindowFromTable(widget)))
|
||||||
|
widget = XtParent(widget);
|
||||||
|
|
||||||
|
if (!widget || !win)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
|
||||||
|
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, event);
|
||||||
|
|
||||||
|
return win->ProcessEvent( keyEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool wxApp::CheckForKeyUp(WXEvent* event) { wxFAIL; return false; }
|
||||||
|
|
||||||
|
bool CheckForKeyUp(XEvent* event)
|
||||||
|
{
|
||||||
|
if (event->xany.type == KeyRelease)
|
||||||
|
{
|
||||||
|
Widget widget = XtWindowToWidget((Display*) wxGetDisplay(),
|
||||||
|
event->xany.window);
|
||||||
|
wxWindow* win = NULL;
|
||||||
|
|
||||||
|
// Find the first wxWindow that corresponds to this event window
|
||||||
|
while (widget && !(win = wxGetWindowFromTable(widget)))
|
||||||
|
widget = XtParent(widget);
|
||||||
|
|
||||||
|
if (!widget || !win)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxKeyEvent keyEvent(wxEVT_KEY_UP);
|
||||||
|
wxTranslateKeyEvent(keyEvent, win, (Widget) 0, event);
|
||||||
|
|
||||||
|
return win->ProcessEvent( keyEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// executes one main loop iteration (declared in include/wx/motif/private.h)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool wxDoEventLoopIteration( wxEventLoop& evtLoop )
|
||||||
|
{
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
// leave the main loop to give other threads a chance to
|
||||||
|
// perform their GUI work
|
||||||
|
wxMutexGuiLeave();
|
||||||
|
wxUsleep(20);
|
||||||
|
wxMutexGuiEnter();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while ( !evtLoop.Pending() && ::SendIdleMessage() )
|
||||||
|
;
|
||||||
|
|
||||||
|
if( !evtLoop.Dispatch() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// ::wxWakeUpIdle implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// As per Vadim's suggestion, we open a pipe, and XtAppAddInputSource it;
|
||||||
|
// writing a single byte to the pipe will cause wxEventLoop::Pending
|
||||||
|
// to return true, and wxEventLoop::Dispatch to dispatch an input handler
|
||||||
|
// that simply removes the byte(s), and to return, which will cause
|
||||||
|
// an idle event to be sent
|
||||||
|
|
||||||
|
// also wxEventLoop::Exit is implemented that way, so that exiting an
|
||||||
|
// event loop won't require an event being in the queue
|
||||||
|
|
||||||
|
#include "wx/module.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static XtInputId inputId;
|
||||||
|
static int idleFds[2] = { -1, -1 };
|
||||||
|
|
||||||
|
class wxIdlePipeModule : public wxModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxIdlePipeModule() {};
|
||||||
|
|
||||||
|
virtual bool OnInit()
|
||||||
|
{
|
||||||
|
if( pipe(idleFds) != 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnExit()
|
||||||
|
{
|
||||||
|
close( idleFds[0] );
|
||||||
|
close( idleFds[1] );
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
DECLARE_DYNAMIC_CLASS(wxIdlePipeModule);
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(wxIdlePipeModule, wxModule);
|
||||||
|
|
||||||
|
static void wxInputCallback( XtPointer, int* fd, XtInputId* )
|
||||||
|
{
|
||||||
|
char buffer[128];
|
||||||
|
|
||||||
|
// wxWakeUpIdle may have been called more than once
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
fd_set in;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO( &in );
|
||||||
|
FD_SET( *fd, &in );
|
||||||
|
|
||||||
|
if( select( *fd + 1, &in, NULL, NULL, &timeout ) <= 0 )
|
||||||
|
break;
|
||||||
|
if( read( *fd, buffer, sizeof(buffer) - 1 ) != sizeof(buffer) - 1 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wxBreakDispatch()
|
||||||
|
{
|
||||||
|
char dummy;
|
||||||
|
|
||||||
|
// check if wxWakeUpIdle has already been called
|
||||||
|
fd_set in;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO( &in );
|
||||||
|
FD_SET( idleFds[0], &in );
|
||||||
|
|
||||||
|
if( select( idleFds[0] + 1, &in, NULL, NULL, &timeout ) > 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// write a single byte
|
||||||
|
write( idleFds[1], &dummy, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxWakeUpIdle()
|
||||||
|
{
|
||||||
|
::wxBreakDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxAddIdleCallback()
|
||||||
|
{
|
||||||
|
// install input handler for wxWakeUpIdle
|
||||||
|
inputId = XtAppAddInput( (XtAppContext) wxTheApp->GetAppContext(),
|
||||||
|
idleFds[0],
|
||||||
|
(XtPointer)XtInputReadMask,
|
||||||
|
wxInputCallback,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@@ -199,6 +199,7 @@ ALL_SOURCES = \
|
|||||||
motif/dcmemory.cpp \
|
motif/dcmemory.cpp \
|
||||||
motif/dcscreen.cpp \
|
motif/dcscreen.cpp \
|
||||||
motif/dialog.cpp \
|
motif/dialog.cpp \
|
||||||
|
motif/evtloop.cpp \
|
||||||
motif/filedlg.cpp \
|
motif/filedlg.cpp \
|
||||||
motif/font.cpp \
|
motif/font.cpp \
|
||||||
motif/frame.cpp \
|
motif/frame.cpp \
|
||||||
@@ -834,6 +835,7 @@ GUIOBJS = \
|
|||||||
dcmemory.o \
|
dcmemory.o \
|
||||||
dcscreen.o \
|
dcscreen.o \
|
||||||
dialog.o \
|
dialog.o \
|
||||||
|
evtloop.o \
|
||||||
filedlg.o \
|
filedlg.o \
|
||||||
font.o \
|
font.o \
|
||||||
frame.o \
|
frame.o \
|
||||||
|
@@ -440,28 +440,20 @@ bool wxMenuBar::DestroyMenuBar()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Motif-specific
|
// Since PopupMenu under Motif stills grab right mouse button events
|
||||||
static XtWorkProcId WorkProcMenuId;
|
// after it was closed, we need to delete the associated widgets to
|
||||||
|
// allow next PopUpMenu to appear...
|
||||||
/* Since PopupMenu under Motif stills grab right mouse button events
|
void wxMenu::DestroyWidgetAndDetach()
|
||||||
* after it was closed, we need to delete the associated widgets to
|
|
||||||
* allow next PopUpMenu to appear...
|
|
||||||
*/
|
|
||||||
|
|
||||||
int PostDeletionOfMenu( XtPointer* clientData )
|
|
||||||
{
|
{
|
||||||
XtRemoveWorkProc(WorkProcMenuId);
|
if (GetMainWidget())
|
||||||
wxMenu *menu = (wxMenu *)clientData;
|
|
||||||
|
|
||||||
if (menu->GetMainWidget())
|
|
||||||
{
|
{
|
||||||
wxMenu *menuParent = menu->GetParent();
|
wxMenu *menuParent = GetParent();
|
||||||
if ( menuParent )
|
if ( menuParent )
|
||||||
{
|
{
|
||||||
wxMenuItemList::Node *node = menuParent->GetMenuItems().GetFirst();
|
wxMenuItemList::Node *node = menuParent->GetMenuItems().GetFirst();
|
||||||
while ( node )
|
while ( node )
|
||||||
{
|
{
|
||||||
if ( node->GetData()->GetSubMenu() == menu )
|
if ( node->GetData()->GetSubMenu() == this )
|
||||||
{
|
{
|
||||||
menuParent->GetMenuItems().DeleteNode(node);
|
menuParent->GetMenuItems().DeleteNode(node);
|
||||||
|
|
||||||
@@ -472,33 +464,11 @@ int PostDeletionOfMenu( XtPointer* clientData )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->DestroyMenu(TRUE);
|
DestroyMenu(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as no longer popped up
|
// Mark as no longer popped up
|
||||||
menu->m_menuId = -1;
|
m_menuId = -1;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wxMenuPopdownCallback(Widget WXUNUSED(w), XtPointer clientData,
|
|
||||||
XtPointer WXUNUSED(ptr))
|
|
||||||
{
|
|
||||||
wxMenu *menu = (wxMenu *)clientData;
|
|
||||||
|
|
||||||
// Added by JOREL Jean-Charles <jjorel@silr.ireste.fr>
|
|
||||||
/* Since Callbacks of MenuItems are not yet processed, we put a
|
|
||||||
* background job which will be done when system will be idle.
|
|
||||||
* What awful hack!! :(
|
|
||||||
*/
|
|
||||||
|
|
||||||
WorkProcMenuId = XtAppAddWorkProc(
|
|
||||||
(XtAppContext) wxTheApp->GetAppContext(),
|
|
||||||
(XtWorkProc) PostDeletionOfMenu,
|
|
||||||
(XtPointer) menu );
|
|
||||||
// Apparently not found in Motif headers
|
|
||||||
// XtVaSetValues( w, XmNpopupEnabled, XmPOPUP_DISABLED, NULL );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -518,10 +488,12 @@ WXWidget wxMenu::CreateMenu (wxMenuBar * menuBar, WXWidget parent, wxMenu * topM
|
|||||||
if (!pullDown)
|
if (!pullDown)
|
||||||
{
|
{
|
||||||
menu = XmCreatePopupMenu ((Widget) parent, "popup", args, 2);
|
menu = XmCreatePopupMenu ((Widget) parent, "popup", args, 2);
|
||||||
|
#if 0
|
||||||
XtAddCallback(menu,
|
XtAddCallback(menu,
|
||||||
XmNunmapCallback,
|
XmNunmapCallback,
|
||||||
(XtCallbackProc)wxMenuPopdownCallback,
|
(XtCallbackProc)wxMenuPopdownCallback,
|
||||||
(XtPointer)this);
|
(XtPointer)this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -354,6 +354,7 @@ void wxMenuItemCallback (Widget WXUNUSED(w), XtPointer clientData,
|
|||||||
|
|
||||||
item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(commandEvent);
|
item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(commandEvent);
|
||||||
}
|
}
|
||||||
|
// this is the child of a popup menu
|
||||||
else if (item->GetTopMenu())
|
else if (item->GetTopMenu())
|
||||||
{
|
{
|
||||||
wxCommandEvent event (wxEVT_COMMAND_MENU_SELECTED, item->GetId());
|
wxCommandEvent event (wxEVT_COMMAND_MENU_SELECTED, item->GetId());
|
||||||
@@ -361,6 +362,14 @@ void wxMenuItemCallback (Widget WXUNUSED(w), XtPointer clientData,
|
|||||||
event.SetInt( item->GetId() );
|
event.SetInt( item->GetId() );
|
||||||
|
|
||||||
item->GetTopMenu()->ProcessCommand (event);
|
item->GetTopMenu()->ProcessCommand (event);
|
||||||
|
|
||||||
|
// Since PopupMenu under Motif stills grab right mouse
|
||||||
|
// button events after it was closed, we need to delete
|
||||||
|
// the associated widgets to allow next PopUpMenu to
|
||||||
|
// appear; this needs to be done there because doing it in
|
||||||
|
// a WorkProc as before may cause crashes if a menu item causes
|
||||||
|
// the parent window of the menu to be destroyed
|
||||||
|
item->GetTopMenu()->DestroyWidgetAndDetach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include "wx/module.h"
|
#include "wx/module.h"
|
||||||
#include "wx/menuitem.h"
|
#include "wx/menuitem.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
|
#include "wx/evtloop.h"
|
||||||
|
|
||||||
#if wxUSE_DRAG_AND_DROP
|
#if wxUSE_DRAG_AND_DROP
|
||||||
#include "wx/dnd.h"
|
#include "wx/dnd.h"
|
||||||
@@ -1151,6 +1152,8 @@ void wxWindow::DoSetToolTip(wxToolTip * WXUNUSED(tooltip))
|
|||||||
// popup menus
|
// popup menus
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if wxUSE_MENUS
|
||||||
|
|
||||||
bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
|
bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
|
||||||
{
|
{
|
||||||
Widget widget = (Widget) GetMainWidget();
|
Widget widget = (Widget) GetMainWidget();
|
||||||
@@ -1165,7 +1168,8 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
|
|||||||
if (menu->GetParent() && (menu->GetId() != -1))
|
if (menu->GetParent() && (menu->GetId() != -1))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (menu->GetMainWidget()) {
|
if (menu->GetMainWidget())
|
||||||
|
{
|
||||||
menu->DestroyMenu(TRUE);
|
menu->DestroyMenu(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1214,7 +1218,6 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
|
|||||||
XmMenuPosition (menuWidget, &event);
|
XmMenuPosition (menuWidget, &event);
|
||||||
XtManageChild (menuWidget);
|
XtManageChild (menuWidget);
|
||||||
|
|
||||||
XEvent x_event;
|
|
||||||
// The ID of a pop-up menu is 1 when active, and is set to 0 by the
|
// The ID of a pop-up menu is 1 when active, and is set to 0 by the
|
||||||
// idle-time destroy routine.
|
// idle-time destroy routine.
|
||||||
// Waiting until this ID changes causes this function to block until
|
// Waiting until this ID changes causes this function to block until
|
||||||
@@ -1222,29 +1225,19 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
|
|||||||
// In other words, once this routine returns, it is safe to delete
|
// In other words, once this routine returns, it is safe to delete
|
||||||
// the menu object.
|
// the menu object.
|
||||||
// Ian Brown <ian.brown@printsoft.de>
|
// Ian Brown <ian.brown@printsoft.de>
|
||||||
|
|
||||||
|
wxEventLoop evtLoop;
|
||||||
|
|
||||||
while (menu->GetId() == 1)
|
while (menu->GetId() == 1)
|
||||||
{
|
{
|
||||||
XtAppNextEvent( (XtAppContext) wxTheApp->GetAppContext(), &x_event);
|
wxDoEventLoopIteration( evtLoop );
|
||||||
|
|
||||||
wxTheApp->ProcessXEvent((WXEvent*) & x_event);
|
|
||||||
|
|
||||||
if (XtAppPending( (XtAppContext) wxTheApp->GetAppContext() ) == 0)
|
|
||||||
{
|
|
||||||
if (!wxTheApp->ProcessIdle())
|
|
||||||
{
|
|
||||||
#if wxUSE_THREADS
|
|
||||||
// leave the main loop to give other threads a chance to
|
|
||||||
// perform their GUI work
|
|
||||||
wxMutexGuiLeave();
|
|
||||||
wxUsleep(20);
|
|
||||||
wxMutexGuiEnter();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// moving and resizing
|
// moving and resizing
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1352,9 +1345,9 @@ void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
|
|||||||
y = oldY;
|
y = oldY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( width == -1 )
|
if ( width <= 0 )
|
||||||
width = oldW;
|
width = oldW;
|
||||||
if ( height == -1 )
|
if ( height <= 0 )
|
||||||
height = oldH;
|
height = oldH;
|
||||||
|
|
||||||
bool nothingChanged = (x == oldX) && (y == oldY) &&
|
bool nothingChanged = (x == oldX) && (y == oldY) &&
|
||||||
@@ -1390,15 +1383,6 @@ void wxWindow::DoSetSizeIntr(int x, int y, int width, int height,
|
|||||||
|
|
||||||
if (managed)
|
if (managed)
|
||||||
XtManageChild(widget);
|
XtManageChild(widget);
|
||||||
|
|
||||||
// How about this bit. Maybe we don't need to generate size events
|
|
||||||
// all the time -- they'll be generated when the window is sized anyway.
|
|
||||||
#if 0
|
|
||||||
wxSizeEvent sizeEvent(wxSize(width, height), GetId());
|
|
||||||
sizeEvent.SetEventObject(this);
|
|
||||||
|
|
||||||
GetEventHandler()->ProcessEvent(sizeEvent);
|
|
||||||
#endif // 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1727,6 +1711,7 @@ void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
|
bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
|
||||||
{
|
{
|
||||||
|
#if wxUSE_ACCEL
|
||||||
if (!m_acceleratorTable.Ok())
|
if (!m_acceleratorTable.Ok())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -1753,6 +1738,7 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
|
|||||||
wxFrame* frame = wxDynamicCast(parent, wxFrame);
|
wxFrame* frame = wxDynamicCast(parent, wxFrame);
|
||||||
if ( frame )
|
if ( frame )
|
||||||
{
|
{
|
||||||
|
#if wxUSE_MENUS
|
||||||
// Try for a menu command
|
// Try for a menu command
|
||||||
if (frame->GetMenuBar())
|
if (frame->GetMenuBar())
|
||||||
{
|
{
|
||||||
@@ -1767,6 +1753,7 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
|
|||||||
return frame->GetEventHandler()->ProcessEvent(commandEvent);
|
return frame->GetEventHandler()->ProcessEvent(commandEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a child matching the command id
|
// Find a child matching the command id
|
||||||
@@ -1788,6 +1775,7 @@ bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
} // matches event
|
} // matches event
|
||||||
}// for
|
}// for
|
||||||
|
#endif
|
||||||
|
|
||||||
// We didn't match the key event against an accelerator.
|
// We didn't match the key event against an accelerator.
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
Reference in New Issue
Block a user