Added X11 wxEventLoop implementation; rearranged event processing
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14064 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -32,6 +32,7 @@ class WXDLLEXPORT wxWindow;
|
||||
class WXDLLEXPORT wxApp;
|
||||
class WXDLLEXPORT wxKeyEvent;
|
||||
class WXDLLEXPORT wxLog;
|
||||
class WXDLLEXPORT wxEventLoop;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// the wxApp class for Motif - see wxAppBase for more details
|
||||
@@ -78,12 +79,6 @@ public:
|
||||
// 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:
|
||||
bool m_showOnInit;
|
||||
|
||||
@@ -114,6 +109,7 @@ protected:
|
||||
WXColormap m_mainColormap;
|
||||
WXDisplay* m_initialDisplay;
|
||||
long m_maxRequestSize;
|
||||
wxEventLoop* m_mainLoop;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: private.h
|
||||
// Purpose: Private declarations for wxMotif port
|
||||
// Purpose: Private declarations for X11 port
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 17/09/98
|
||||
@@ -17,27 +17,26 @@
|
||||
class wxMouseEvent;
|
||||
class wxKeyEvent;
|
||||
|
||||
// Put any private declarations here: native Motif types may be used because
|
||||
// this header is included after Xm/Xm.h
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// common callbacks
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
// All widgets should have this as their resize proc.
|
||||
extern void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *num_args);
|
||||
|
||||
// For repainting arbitrary windows
|
||||
void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *);
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// we maintain a hash table which contains the mapping from Widget to wxWindow
|
||||
// corresponding to the window for this widget
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern void wxDeleteWindowFromTable(Widget w);
|
||||
extern wxWindow *wxGetWindowFromTable(Widget w);
|
||||
extern bool wxAddWindowToTable(Widget w, wxWindow *win);
|
||||
extern void wxDeleteWindowFromTable(Window w);
|
||||
extern wxWindow *wxGetWindowFromTable(Window w);
|
||||
extern bool wxAddWindowToTable(Window w, wxWindow *win);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// key events related functions
|
||||
@@ -46,7 +45,7 @@ extern bool wxAddWindowToTable(Widget w, wxWindow *win);
|
||||
extern char wxFindMnemonic(const char* s);
|
||||
|
||||
extern char * wxFindAccelerator (const char *s);
|
||||
extern XmString wxFindAcceleratorText (const char *s);
|
||||
//extern XmString wxFindAcceleratorText (const char *s);
|
||||
|
||||
extern int wxCharCodeXToWX(KeySym keySym);
|
||||
extern KeySym wxCharCodeWXToX(int id);
|
||||
@@ -54,8 +53,8 @@ extern KeySym wxCharCodeWXToX(int id);
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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 bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent);
|
||||
extern bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window window, XEvent *xevent);
|
||||
|
||||
int wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap);
|
||||
Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap );
|
||||
@@ -78,43 +77,11 @@ extern XColor itemColors[5] ;
|
||||
#define wxTOPS_INDEX 3
|
||||
#define wxBOTS_INDEX 4
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// utility classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// XmString made easy to use in wxWindows (and has an added benefit of
|
||||
// cleaning up automatically)
|
||||
class wxXmString
|
||||
{
|
||||
public:
|
||||
wxXmString(const wxString& str)
|
||||
{
|
||||
m_string = XmStringCreateLtoR((char *)str.c_str(),
|
||||
XmSTRING_DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
~wxXmString() { XmStringFree(m_string); }
|
||||
|
||||
// semi-implicit conversion to XmString (shouldn't rely on implicit
|
||||
// conversion because many of Motif functions are macros)
|
||||
XmString operator()() const { return m_string; }
|
||||
|
||||
private:
|
||||
XmString m_string;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// macros to avoid casting WXFOO to Foo all the time
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// argument is of type "wxWindow *"
|
||||
#define GetWidget(w) ((Widget)(w)->GetHandle())
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// accessors for C modules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern "C" XtAppContext wxGetAppContext();
|
||||
// extern "C" XtAppContext wxGetAppContext();
|
||||
|
||||
#endif
|
||||
// _WX_PRIVATE_H_
|
||||
|
@@ -1,26 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/motif/frame.h
|
||||
// Purpose: wxFrame class
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/x11/toplevel.h
|
||||
// Purpose: wxTopLevelWindowX11 is the X11 implementation of wxTLW
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 17/09/98
|
||||
// Created: 20.09.01
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart
|
||||
// Copyright: (c) 2002 Julian Smart
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_MOTIF_FRAME_H_
|
||||
#define _WX_MOTIF_FRAME_H_
|
||||
#ifndef _WX_X11_TOPLEVEL_H_
|
||||
#define _WX_X11_TOPLEVEL_H_
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "frame.h"
|
||||
#pragma interface "toplevel.h"
|
||||
#endif
|
||||
|
||||
class WXDLLEXPORT wxFrame : public wxFrameBase
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTopLevelWindowX11
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxTopLevelWindowX11 : public wxTopLevelWindowBase
|
||||
{
|
||||
public:
|
||||
wxFrame() { Init(); }
|
||||
wxFrame(wxWindow *parent,
|
||||
// constructors and such
|
||||
wxTopLevelWindowX11() { Init(); }
|
||||
|
||||
wxTopLevelWindowX11(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
@@ -30,7 +36,7 @@ public:
|
||||
{
|
||||
Init();
|
||||
|
||||
Create(parent, id, title, pos, size, style, name);
|
||||
(void)Create(parent, id, title, pos, size, style, name);
|
||||
}
|
||||
|
||||
bool Create(wxWindow *parent,
|
||||
@@ -41,94 +47,55 @@ public:
|
||||
long style = wxDEFAULT_FRAME_STYLE,
|
||||
const wxString& name = wxFrameNameStr);
|
||||
|
||||
virtual ~wxFrame();
|
||||
virtual ~wxTopLevelWindowX11();
|
||||
|
||||
// implement base class pure virtuals
|
||||
virtual void Maximize(bool maximize = TRUE);
|
||||
virtual bool IsMaximized() const;
|
||||
virtual void Iconize(bool iconize = TRUE);
|
||||
virtual bool IsIconized() const;
|
||||
virtual void SetIcon(const wxIcon& icon);
|
||||
virtual void Restore();
|
||||
|
||||
virtual bool Show(bool show = TRUE);
|
||||
|
||||
// Set menu bar
|
||||
void SetMenuBar(wxMenuBar *menu_bar);
|
||||
virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL);
|
||||
virtual bool IsFullScreen() const { return m_fsIsShowing; }
|
||||
|
||||
// Set title
|
||||
void SetTitle(const wxString& title);
|
||||
wxString GetTitle() const { return m_title; }
|
||||
|
||||
// Set icon
|
||||
virtual void SetIcon(const wxIcon& icon);
|
||||
|
||||
#if wxUSE_STATUSBAR
|
||||
virtual void PositionStatusBar();
|
||||
#endif // wxUSE_STATUSBAR
|
||||
|
||||
// Create toolbar
|
||||
#if wxUSE_TOOLBAR
|
||||
virtual wxToolBar* CreateToolBar(long style = wxNO_BORDER|wxTB_HORIZONTAL, wxWindowID id = -1, const wxString& name = wxToolBarNameStr);
|
||||
virtual void PositionToolBar();
|
||||
#endif // wxUSE_TOOLBAR
|
||||
|
||||
// Iconize
|
||||
virtual void Iconize(bool iconize);
|
||||
|
||||
virtual bool IsIconized() const;
|
||||
|
||||
// Is the frame maximized? Returns FALSE under Motif (but TRUE for
|
||||
// wxMDIChildFrame due to the tabbed implementation).
|
||||
virtual bool IsMaximized() const;
|
||||
|
||||
virtual void Maximize(bool maximize);
|
||||
|
||||
virtual void Raise();
|
||||
virtual void Lower();
|
||||
|
||||
virtual void Restore();
|
||||
|
||||
// Implementation only from now on
|
||||
// -------------------------------
|
||||
|
||||
void OnSysColourChanged(wxSysColourChangedEvent& event);
|
||||
void OnActivate(wxActivateEvent& event);
|
||||
|
||||
virtual void ChangeFont(bool keepOriginalSize = TRUE);
|
||||
virtual void ChangeBackgroundColour();
|
||||
virtual void ChangeForegroundColour();
|
||||
WXWidget GetMenuBarWidget() const;
|
||||
WXWidget GetShellWidget() const { return m_frameShell; }
|
||||
WXWidget GetWorkAreaWidget() const { return m_workArea; }
|
||||
WXWidget GetClientAreaWidget() const { return m_clientArea; }
|
||||
WXWidget GetTopWidget() const { return m_frameShell; }
|
||||
|
||||
virtual WXWidget GetMainWidget() const { return m_frameWidget; }
|
||||
|
||||
// The widget that can have children on it
|
||||
WXWidget GetClientWidget() const;
|
||||
bool GetVisibleStatus() const { return m_visibleStatus; }
|
||||
|
||||
bool PreResize();
|
||||
// implementation from now on
|
||||
// --------------------------
|
||||
|
||||
protected:
|
||||
// common part of all ctors
|
||||
void Init();
|
||||
|
||||
//// Motif-specific
|
||||
WXWidget m_frameShell;
|
||||
WXWidget m_frameWidget;
|
||||
WXWidget m_workArea;
|
||||
WXWidget m_clientArea;
|
||||
wxString m_title;
|
||||
bool m_visibleStatus;
|
||||
// create a new frame, return FALSE if it couldn't be created
|
||||
bool CreateFrame(const wxString& title,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size);
|
||||
|
||||
// create a new dialog using the given dialog template from resources,
|
||||
// return FALSE if it couldn't be created
|
||||
bool CreateDialog(const wxString& title,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size);
|
||||
|
||||
// is the frame currently iconized?
|
||||
bool m_iconized;
|
||||
|
||||
virtual void DoGetClientSize(int *width, int *height) const;
|
||||
virtual void DoGetSize(int *width, int *height) const;
|
||||
virtual void DoGetPosition(int *x, int *y) const;
|
||||
virtual void DoSetSize(int x, int y,
|
||||
int width, int height,
|
||||
int sizeFlags = wxSIZE_AUTO);
|
||||
virtual void DoSetClientSize(int width, int height);
|
||||
// should the frame be maximized when it will be shown? set by Maximize()
|
||||
// when it is called while the frame is hidden
|
||||
bool m_maximizeOnShow;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
DECLARE_DYNAMIC_CLASS(wxFrame)
|
||||
// Data to save/restore when calling ShowFullScreen
|
||||
long m_fsStyle; // Passed to ShowFullScreen
|
||||
wxRect m_fsOldSize;
|
||||
bool m_fsIsMaximized;
|
||||
bool m_fsIsShowing;
|
||||
};
|
||||
|
||||
#endif
|
||||
// _WX_MOTIF_FRAME_H_
|
||||
// list of all frames and modeless dialogs
|
||||
;; extern WXDLLEXPORT_DATA(wxWindowList) wxModelessWindows;
|
||||
|
||||
#endif // _WX_X11_TOPLEVEL_H_
|
||||
|
||||
|
270
src/x11/app.cpp
270
src/x11/app.cpp
@@ -30,6 +30,7 @@
|
||||
#include "wx/memory.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
#if wxUSE_THREADS
|
||||
#include "wx/thread.h"
|
||||
@@ -68,15 +69,15 @@ BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
|
||||
typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *);
|
||||
|
||||
XErrorHandlerFunc gs_pfnXErrorHandler = 0;
|
||||
XErrorHandlerFunc gs_pfnXErrorHandler = 0;
|
||||
|
||||
static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
|
||||
{
|
||||
static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent)
|
||||
{
|
||||
// just forward to the default handler for now
|
||||
return gs_pfnXErrorHandler(dpy, xevent);
|
||||
}
|
||||
}
|
||||
#endif // __WXDEBUG__
|
||||
|
||||
long wxApp::sm_lastMessageTime = 0;
|
||||
@@ -259,6 +260,7 @@ wxApp::wxApp()
|
||||
m_topLevelWidget = (WXWindow) NULL;
|
||||
m_maxRequestSize = 0;
|
||||
m_initialDisplay = (WXDisplay*) 0;
|
||||
m_mainLoop = NULL;
|
||||
}
|
||||
|
||||
bool wxApp::Initialized()
|
||||
@@ -271,45 +273,14 @@ bool wxApp::Initialized()
|
||||
|
||||
int wxApp::MainLoop()
|
||||
{
|
||||
m_keepGoing = TRUE;
|
||||
int rt;
|
||||
m_mainLoop = new wxEventLoop;
|
||||
|
||||
/*
|
||||
* Sit around forever waiting to process X-events. Property Change
|
||||
* event are handled special, because they have to refer to
|
||||
* the root window rather than to a widget. therefore we can't
|
||||
* use an Xt-eventhandler.
|
||||
*/
|
||||
rt = m_mainLoop->Run();
|
||||
|
||||
XSelectInput(wxGetDisplay(),
|
||||
XDefaultRootWindow(wxGetDisplay()),
|
||||
PropertyChangeMask);
|
||||
|
||||
XEvent event;
|
||||
|
||||
// Use this flag to allow breaking the loop via wxApp::ExitMainLoop()
|
||||
while (m_keepGoing)
|
||||
{
|
||||
XNextEvent(wxGetDisplay(), & event);
|
||||
|
||||
ProcessXEvent((WXEvent*) & event);
|
||||
|
||||
if (XtPending(wxGetDisplay()) == 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;
|
||||
delete m_mainLoop;
|
||||
m_mainLoop = NULL;
|
||||
return rt;
|
||||
}
|
||||
|
||||
// Processes an X event.
|
||||
@@ -317,7 +288,21 @@ void wxApp::ProcessXEvent(WXEvent* _event)
|
||||
{
|
||||
XEvent* event = (XEvent*) _event;
|
||||
|
||||
if (event->type == KeyPress)
|
||||
wxWindow* win = NULL;
|
||||
Window window = event->xany.window;
|
||||
Window actualWindow = window;
|
||||
|
||||
// Find the first wxWindow that corresponds to this event window
|
||||
// TODO: may need to translate coordinates from actualWindow
|
||||
// to window, if the receiving window != wxWindow window
|
||||
while (window && !(win = wxGetWindowFromTable(window)))
|
||||
window = XGetParent(window);
|
||||
|
||||
// TODO: shouldn't all the ProcessEvents below
|
||||
// be win->GetEventHandler()->ProcessEvent?
|
||||
switch (event->type)
|
||||
{
|
||||
case KeyPress:
|
||||
{
|
||||
if (CheckForAccelerator(_event))
|
||||
{
|
||||
@@ -325,49 +310,44 @@ void wxApp::ProcessXEvent(WXEvent* _event)
|
||||
// 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))
|
||||
else
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
|
||||
wxTranslateKeyEvent(keyEvent, win, window, xEvent);
|
||||
|
||||
// We didn't process wxEVT_KEY_DOWN, so send
|
||||
// wxEVT_KEY_CHAR
|
||||
if (!win->ProcessEvent( keyEvent ))
|
||||
{
|
||||
keyEvent.SetEventType(wxEVT_KEY_CHAR);
|
||||
win->ProcessEvent( keyEvent );
|
||||
}
|
||||
|
||||
// We intercepted and processed the key down event
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// TODO for X11 implementation -- the equivalent of XtDispatchEvent.
|
||||
// Presumably, we need to form the wxEvents and
|
||||
// and send them to the appropriate windows.
|
||||
// XtDispatchEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case KeyRelease:
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
wxKeyEvent keyEvent(wxEVT_KEY_UP);
|
||||
wxTranslateKeyEvent(keyEvent, win, window, event);
|
||||
|
||||
win->ProcessEvent( keyEvent );
|
||||
}
|
||||
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
|
||||
{
|
||||
// TODO: The X equivalent of XtDispatchEvent
|
||||
// (see above)
|
||||
// XtDispatchEvent(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (event->type == PropertyNotify)
|
||||
case PropertyNotify:
|
||||
{
|
||||
HandlePropertyChange(_event);
|
||||
return;
|
||||
}
|
||||
else if (event->type == ResizeRequest)
|
||||
case ResizeRequest:
|
||||
{
|
||||
/* Terry Gitnick <terryg@scientech.com> - 1/21/98
|
||||
* If resize event, don't resize until the last resize event for this
|
||||
@@ -375,27 +355,86 @@ void wxApp::ProcessXEvent(WXEvent* _event)
|
||||
*/
|
||||
|
||||
Display *disp = wxGetDisplay();
|
||||
Window win = event->xany.window;
|
||||
XEvent report;
|
||||
|
||||
// to avoid flicker
|
||||
report = * event;
|
||||
while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report));
|
||||
while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report));
|
||||
|
||||
// TODO: when implementing refresh optimization, we can use
|
||||
// XtAddExposureToRegion to expand the window's paint region.
|
||||
|
||||
// TODO: generate resize event
|
||||
// XtDispatchEvent(event);
|
||||
}
|
||||
else
|
||||
if (win)
|
||||
{
|
||||
// TODO: generate all other events
|
||||
// XtDispatchEvent(event);
|
||||
wxSize sz = win->GetSize();
|
||||
wxSizeEvent sizeEvent(sz, win->GetId());
|
||||
sizeEvent.SetEventObject(win);
|
||||
|
||||
win->ProcessEvent( wxevent );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case Expose:
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
|
||||
if (event -> xexpose.count == 0)
|
||||
{
|
||||
win->DoPaint();
|
||||
win->ClearUpdateRects();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
case MotionNotify:
|
||||
{
|
||||
if (win)
|
||||
{
|
||||
wxMouseEvent wxevent;
|
||||
wxTranslateMouseEvent(wxevent, win, window, event);
|
||||
win->ProcessEvent( wxevent );
|
||||
}
|
||||
return;
|
||||
}
|
||||
case FocusIn:
|
||||
{
|
||||
if (win && event->xfocus.detail != NotifyPointer)
|
||||
{
|
||||
wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId());
|
||||
focusEvent.SetEventObject(win);
|
||||
win->ProcessEvent(focusEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FocusOut:
|
||||
{
|
||||
if (win && event->xfocus.detail != NotifyPointer)
|
||||
{
|
||||
wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId());
|
||||
focusEvent.SetEventObject(win);
|
||||
win->ProcessEvent(focusEvent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns TRUE if more time is needed.
|
||||
// Note that this duplicates wxEventLoopImpl::SendIdleEvent
|
||||
// but ProcessIdle may be needed by apps, so is kept.
|
||||
bool wxApp::ProcessIdle()
|
||||
{
|
||||
wxIdleEvent event;
|
||||
@@ -407,23 +446,20 @@ bool wxApp::ProcessIdle()
|
||||
|
||||
void wxApp::ExitMainLoop()
|
||||
{
|
||||
m_keepGoing = FALSE;
|
||||
if (m_mainLoop)
|
||||
m_mainLoop->Exit(0);
|
||||
}
|
||||
|
||||
// Is a message/event pending?
|
||||
bool wxApp::Pending()
|
||||
{
|
||||
XFlush(wxGetDisplay());
|
||||
|
||||
return (XPending(wxGetDisplay()) > 0);
|
||||
return wxEventLoop::GetActive()->Pending();
|
||||
}
|
||||
|
||||
// Dispatch a message.
|
||||
void wxApp::Dispatch()
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(wxGetDisplay(), & event);
|
||||
ProcessXEvent((WXEvent*) & event);
|
||||
wxEventLoop::GetActive()->Dispatch();
|
||||
}
|
||||
|
||||
// This should be redefined in a derived class for
|
||||
@@ -553,19 +589,15 @@ bool wxApp::OnInitGui()
|
||||
(const char*) className);
|
||||
exit(-1);
|
||||
}
|
||||
XSelectInput(m_initialDisplay,
|
||||
XDefaultRootWindow(m_initialDisplay),
|
||||
PropertyChangeMask);
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
// install the X error handler
|
||||
gs_pfnXErrorHandler = XSetErrorHandler(wxXErrorHandler);
|
||||
#endif // __WXDEBUG__
|
||||
|
||||
// Do we need to create the top-level window initially?
|
||||
#if 0
|
||||
wxTheApp->m_topLevelWidget = (WXWidget) XtAppCreateShell((String)NULL, (const char*) wxTheApp->GetClassName(),
|
||||
applicationShellWidgetClass,dpy,
|
||||
NULL,0) ;
|
||||
#endif
|
||||
|
||||
GetMainColormap(dpy);
|
||||
m_maxRequestSize = XMaxRequestSize((Display*) dpy);
|
||||
|
||||
@@ -634,54 +666,6 @@ bool wxApp::CheckForAccelerator(WXEvent* event)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxApp::CheckForKeyDown(WXEvent* event)
|
||||
{
|
||||
XEvent* xEvent = (XEvent*) event;
|
||||
if (xEvent->xany.type == KeyPress)
|
||||
{
|
||||
Window window = xEvent->xany.window;
|
||||
wxWindow* win = NULL;
|
||||
|
||||
// Find the first wxWindow that corresponds to this event window
|
||||
while (window && !(win = wxGetWindowFromTable(window)))
|
||||
window = XGetParent(window);
|
||||
|
||||
if (!window || !win)
|
||||
return FALSE;
|
||||
|
||||
wxKeyEvent keyEvent(wxEVT_KEY_DOWN);
|
||||
wxTranslateKeyEvent(keyEvent, win, (Window) 0, xEvent);
|
||||
|
||||
return win->ProcessEvent( keyEvent );
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxApp::CheckForKeyUp(WXEvent* event)
|
||||
{
|
||||
XEvent* xEvent = (XEvent*) event;
|
||||
if (xEvent->xany.type == KeyRelease)
|
||||
{
|
||||
Window window = xEvent->xany.window;
|
||||
wxWindow* win = NULL;
|
||||
|
||||
// Find the first wxWindow that corresponds to this event window
|
||||
while (window && !(win = wxGetWindowFromTable(window)))
|
||||
window = XGetParent(window);
|
||||
|
||||
if (!window || !win)
|
||||
return FALSE;
|
||||
|
||||
wxKeyEvent keyEvent(wxEVT_KEY_UP);
|
||||
wxTranslateKeyEvent(keyEvent, win, (Window) 0, xEvent);
|
||||
|
||||
return win->ProcessEvent( keyEvent );
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void wxExit()
|
||||
{
|
||||
int retValue = 0;
|
||||
|
222
src/x11/evtloop.cpp
Normal file
222
src/x11/evtloop.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: x11/evtloop.cpp
|
||||
// Purpose: implements wxEventLoop for X11
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 01.06.01
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2002 Julian Smart
|
||||
// License: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "evtloop.h"
|
||||
#endif
|
||||
|
||||
#include "wx/window.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/evtloop.h"
|
||||
#include "wx/tooltip.h"
|
||||
|
||||
#include "wx/x11/private.h"
|
||||
#include "X11/Xlib.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoopImpl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxEventLoopImpl
|
||||
{
|
||||
public:
|
||||
// ctor
|
||||
wxEventLoopImpl() { SetExitCode(0); m_keepGoing = FALSE; }
|
||||
|
||||
// process an XEvent
|
||||
void ProcessEvent(XEvent* event);
|
||||
|
||||
// generate an idle message, return TRUE if more idle time requested
|
||||
bool SendIdleEvent();
|
||||
|
||||
// set/get the exit code
|
||||
void SetExitCode(int exitcode) { m_exitcode = exitcode; }
|
||||
int GetExitCode() const { return m_exitcode; }
|
||||
|
||||
public:
|
||||
// preprocess an event, return TRUE if processed (i.e. no further
|
||||
// dispatching required)
|
||||
bool PreProcessMessage(XEvent* event);
|
||||
|
||||
// the exit code of the event loop
|
||||
int m_exitcode;
|
||||
|
||||
bool m_keepGoing;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// wxEventLoopImpl implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoopImpl message processing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxEventLoopImpl::ProcessEvent(XEvent *event)
|
||||
{
|
||||
// give us the chance to preprocess the message first
|
||||
if ( !PreProcessEvent(event) )
|
||||
{
|
||||
// if it wasn't done, dispatch it to the corresponding window
|
||||
if (wxTheApp)
|
||||
wxTheApp->ProcessXEvent((WXEvent*) event);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxEventLoopImpl::PreProcessEvent(XEvent *event)
|
||||
{
|
||||
// TODO
|
||||
#if 0
|
||||
HWND hWnd = msg->hwnd;
|
||||
wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
|
||||
|
||||
|
||||
// try translations first; find the youngest window with a translation
|
||||
// table.
|
||||
wxWindow *wnd;
|
||||
for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
|
||||
{
|
||||
if ( wnd->MSWTranslateMessage((WXMSG *)msg) )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Anyone for a non-translation message? Try youngest descendants first.
|
||||
for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
|
||||
{
|
||||
if ( wnd->MSWProcessMessage((WXMSG *)msg) )
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoopImpl idle event processing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxEventLoopImpl::SendIdleEvent()
|
||||
{
|
||||
wxIdleEvent event;
|
||||
event.SetEventObject(wxTheApp);
|
||||
|
||||
return wxTheApp->ProcessEvent(event) && event.MoreRequested();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxEventLoop implementation
|
||||
// ============================================================================
|
||||
|
||||
wxEventLoop *wxEventLoop::ms_activeLoop = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoop running and exiting
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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") );
|
||||
|
||||
m_impl = new wxEventLoopImpl;
|
||||
|
||||
wxEventLoop *oldLoop = ms_activeLoop;
|
||||
ms_activeLoop = this;
|
||||
|
||||
m_impl->m_keepGoing = TRUE;
|
||||
while ( m_impl->m_keepGoing )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
// generate and process idle events for as long as we don't have
|
||||
// anything else to do
|
||||
while ( ! Pending() )
|
||||
{
|
||||
if (!m_impl->SendIdleEvent())
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
// leave the main loop to give other threads a chance to
|
||||
// perform their GUI work
|
||||
wxMutexGuiLeave();
|
||||
wxUsleep(20);
|
||||
wxMutexGuiEnter();
|
||||
#endif
|
||||
// Break out of while loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// a message came or no more idle processing to do, sit in Dispatch()
|
||||
// waiting for the next message
|
||||
if ( !Dispatch() )
|
||||
{
|
||||
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->m_keepGoing = FALSE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoop message processing dispatching
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxEventLoop::Pending() const
|
||||
{
|
||||
XFlush(wxGetDisplay());
|
||||
return (XPending(wxGetDisplay()) > 0);
|
||||
}
|
||||
|
||||
bool wxEventLoop::Dispatch()
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
// TODO allowing for threads, as per e.g. wxMSW
|
||||
|
||||
XNextEvent(wxGetDisplay(), & event);
|
||||
m_impl->ProcessEvent(& event);
|
||||
return TRUE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -61,22 +61,6 @@ static const int SCROLL_MARGIN = 4;
|
||||
extern wxHashTable *wxWidgetHashTable;
|
||||
static wxWindow* g_captureWindow = NULL;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void wxCanvasRepaintProc(Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
|
||||
static void wxCanvasInputEvent(Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
|
||||
static void wxCanvasMotionEvent(Widget, XButtonEvent * event);
|
||||
static void wxCanvasEnterLeave(Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
|
||||
static void wxScrollBarCallback(Widget widget, XtPointer clientData,
|
||||
XmScrollBarCallbackStruct *cbs);
|
||||
static void wxPanelItemEventHandler(Widget wid,
|
||||
XtPointer client_data,
|
||||
XEvent* event,
|
||||
Boolean *continueToDispatch);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// macros
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -1583,401 +1567,8 @@ WXWindow wxWindowX11::GetLabelWindow() const
|
||||
// callbacks
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO
|
||||
// TODO: implement wxWindow scrollbar, presumably using wxScrollBar
|
||||
#if 0
|
||||
|
||||
// All widgets should have this as their resize proc.
|
||||
// OnSize sent to wxWindow via client data.
|
||||
void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event), String WXUNUSED(args)[], int *WXUNUSED(num_args))
|
||||
{
|
||||
wxWindow *win = wxGetWindowFromTable(w);
|
||||
if (!win)
|
||||
return;
|
||||
|
||||
if (win->PreResize())
|
||||
{
|
||||
int width, height;
|
||||
win->GetSize(&width, &height);
|
||||
wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
|
||||
sizeEvent.SetEventObject(win);
|
||||
win->GetEventHandler()->ProcessEvent(sizeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
static void wxCanvasRepaintProc(Widget drawingArea,
|
||||
XtPointer clientData,
|
||||
XmDrawingAreaCallbackStruct * cbs)
|
||||
{
|
||||
if (!wxGetWindowFromTable(drawingArea))
|
||||
return;
|
||||
|
||||
XEvent * event = cbs->event;
|
||||
wxWindow * win = (wxWindow *) clientData;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case Expose:
|
||||
{
|
||||
win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
|
||||
if (event -> xexpose.count == 0)
|
||||
{
|
||||
win->DoPaint();
|
||||
win->ClearUpdateRects();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
|
||||
static void wxCanvasEnterLeave(Widget drawingArea,
|
||||
XtPointer WXUNUSED(clientData),
|
||||
XCrossingEvent * event)
|
||||
{
|
||||
XmDrawingAreaCallbackStruct cbs;
|
||||
XEvent ev;
|
||||
|
||||
((XCrossingEvent &) ev) = *event;
|
||||
|
||||
cbs.reason = XmCR_INPUT;
|
||||
cbs.event = &ev;
|
||||
|
||||
wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
|
||||
}
|
||||
|
||||
// Fix to make it work under Motif 1.0 (!)
|
||||
static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea), XButtonEvent * WXUNUSED(event))
|
||||
{
|
||||
#if XmVersion <= 1000
|
||||
XmDrawingAreaCallbackStruct cbs;
|
||||
XEvent ev;
|
||||
|
||||
ev = *((XEvent *) event);
|
||||
cbs.reason = XmCR_INPUT;
|
||||
cbs.event = &ev;
|
||||
|
||||
wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
|
||||
#endif // XmVersion <= 1000
|
||||
}
|
||||
|
||||
static void wxCanvasInputEvent(Widget drawingArea,
|
||||
XtPointer WXUNUSED(data),
|
||||
XmDrawingAreaCallbackStruct * cbs)
|
||||
{
|
||||
wxWindow *canvas = wxGetWindowFromTable(drawingArea);
|
||||
XEvent local_event;
|
||||
|
||||
if (canvas==NULL)
|
||||
return;
|
||||
|
||||
if (cbs->reason != XmCR_INPUT)
|
||||
return;
|
||||
|
||||
local_event = *(cbs->event); // We must keep a copy!
|
||||
|
||||
switch (local_event.xany.type)
|
||||
{
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
case MotionNotify:
|
||||
{
|
||||
// FIXME: most of this mouse event code is more or less
|
||||
// duplicated in wxTranslateMouseEvent
|
||||
//
|
||||
wxEventType eventType = wxEVT_NULL;
|
||||
|
||||
if (local_event.xany.type == EnterNotify)
|
||||
{
|
||||
//if (local_event.xcrossing.mode!=NotifyNormal)
|
||||
// return ; // Ignore grab events
|
||||
eventType = wxEVT_ENTER_WINDOW;
|
||||
// canvas->GetEventHandler()->OnSetFocus();
|
||||
}
|
||||
else if (local_event.xany.type == LeaveNotify)
|
||||
{
|
||||
//if (local_event.xcrossingr.mode!=NotifyNormal)
|
||||
// return ; // Ignore grab events
|
||||
eventType = wxEVT_LEAVE_WINDOW;
|
||||
// canvas->GetEventHandler()->OnKillFocus();
|
||||
}
|
||||
else if (local_event.xany.type == MotionNotify)
|
||||
{
|
||||
eventType = wxEVT_MOTION;
|
||||
}
|
||||
|
||||
else if (local_event.xany.type == ButtonPress)
|
||||
{
|
||||
if (local_event.xbutton.button == Button1)
|
||||
{
|
||||
eventType = wxEVT_LEFT_DOWN;
|
||||
canvas->SetButton1(TRUE);
|
||||
}
|
||||
else if (local_event.xbutton.button == Button2)
|
||||
{
|
||||
eventType = wxEVT_MIDDLE_DOWN;
|
||||
canvas->SetButton2(TRUE);
|
||||
}
|
||||
else if (local_event.xbutton.button == Button3)
|
||||
{
|
||||
eventType = wxEVT_RIGHT_DOWN;
|
||||
canvas->SetButton3(TRUE);
|
||||
}
|
||||
}
|
||||
else if (local_event.xany.type == ButtonRelease)
|
||||
{
|
||||
if (local_event.xbutton.button == Button1)
|
||||
{
|
||||
eventType = wxEVT_LEFT_UP;
|
||||
canvas->SetButton1(FALSE);
|
||||
}
|
||||
else if (local_event.xbutton.button == Button2)
|
||||
{
|
||||
eventType = wxEVT_MIDDLE_UP;
|
||||
canvas->SetButton2(FALSE);
|
||||
}
|
||||
else if (local_event.xbutton.button == Button3)
|
||||
{
|
||||
eventType = wxEVT_RIGHT_UP;
|
||||
canvas->SetButton3(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
wxMouseEvent wxevent (eventType);
|
||||
|
||||
wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
|
||||
|| (event_left_is_down (&local_event)
|
||||
&& (eventType != wxEVT_LEFT_UP)));
|
||||
wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
|
||||
|| (event_middle_is_down (&local_event)
|
||||
&& (eventType != wxEVT_MIDDLE_UP)));
|
||||
wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
|
||||
|| (event_right_is_down (&local_event)
|
||||
&& (eventType != wxEVT_RIGHT_UP)));
|
||||
|
||||
wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
|
||||
wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
|
||||
wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
|
||||
wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
|
||||
wxevent.SetTimestamp(local_event.xbutton.time);
|
||||
|
||||
if ( eventType == wxEVT_MOTION )
|
||||
{
|
||||
if (local_event.xmotion.is_hint == NotifyHint)
|
||||
{
|
||||
Window root, child;
|
||||
Display *dpy = XtDisplay (drawingArea);
|
||||
|
||||
XQueryPointer (dpy, XtWindow (drawingArea),
|
||||
&root, &child,
|
||||
&local_event.xmotion.x_root,
|
||||
&local_event.xmotion.y_root,
|
||||
&local_event.xmotion.x,
|
||||
&local_event.xmotion.y,
|
||||
&local_event.xmotion.state);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// Now check if we need to translate this event into a double click
|
||||
if (TRUE) // canvas->doubleClickAllowed)
|
||||
{
|
||||
if (wxevent.ButtonDown())
|
||||
{
|
||||
long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay());
|
||||
|
||||
// get button and time-stamp
|
||||
int button = 0;
|
||||
if (wxevent.LeftDown())
|
||||
button = 1;
|
||||
else if (wxevent.MiddleDown())
|
||||
button = 2;
|
||||
else if (wxevent.RightDown())
|
||||
button = 3;
|
||||
long ts = wxevent.GetTimestamp();
|
||||
|
||||
// check, if single or double click
|
||||
int buttonLast = canvas->GetLastClickedButton();
|
||||
long lastTS = canvas->GetLastClickTime();
|
||||
if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime )
|
||||
{
|
||||
// I have a dclick
|
||||
canvas->SetLastClick(0, ts);
|
||||
|
||||
wxEventType typeDouble;
|
||||
if ( eventType == wxEVT_LEFT_DOWN )
|
||||
typeDouble = wxEVT_LEFT_DCLICK;
|
||||
else if ( eventType == wxEVT_MIDDLE_DOWN )
|
||||
typeDouble = wxEVT_MIDDLE_DCLICK;
|
||||
else if ( eventType == wxEVT_RIGHT_DOWN )
|
||||
typeDouble = wxEVT_RIGHT_DCLICK;
|
||||
else
|
||||
typeDouble = wxEVT_NULL;
|
||||
|
||||
if ( typeDouble != wxEVT_NULL )
|
||||
{
|
||||
wxevent.SetEventType(typeDouble);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not fast enough or different button
|
||||
canvas->SetLastClick(button, ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxevent.SetId(canvas->GetId());
|
||||
wxevent.SetEventObject(canvas);
|
||||
wxevent.m_x = local_event.xbutton.x;
|
||||
wxevent.m_y = local_event.xbutton.y;
|
||||
canvas->GetEventHandler()->ProcessEvent (wxevent);
|
||||
#if 0
|
||||
if (eventType == wxEVT_ENTER_WINDOW ||
|
||||
eventType == wxEVT_LEAVE_WINDOW ||
|
||||
eventType == wxEVT_MOTION
|
||||
)
|
||||
return;
|
||||
#endif // 0
|
||||
break;
|
||||
}
|
||||
case KeyPress:
|
||||
{
|
||||
KeySym keySym;
|
||||
#if 0
|
||||
XComposeStatus compose;
|
||||
(void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, &compose);
|
||||
#endif // 0
|
||||
|
||||
(void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
|
||||
int id = wxCharCodeXToWX (keySym);
|
||||
|
||||
wxEventType eventType = wxEVT_CHAR;
|
||||
|
||||
wxKeyEvent event (eventType);
|
||||
|
||||
if (local_event.xkey.state & ShiftMask)
|
||||
event.m_shiftDown = TRUE;
|
||||
if (local_event.xkey.state & ControlMask)
|
||||
event.m_controlDown = TRUE;
|
||||
if (local_event.xkey.state & Mod3Mask)
|
||||
event.m_altDown = TRUE;
|
||||
if (local_event.xkey.state & Mod1Mask)
|
||||
event.m_metaDown = TRUE;
|
||||
event.SetEventObject(canvas);
|
||||
event.m_keyCode = id;
|
||||
event.SetTimestamp(local_event.xkey.time);
|
||||
|
||||
if (id > -1)
|
||||
{
|
||||
// Implement wxFrame::OnCharHook by checking ancestor.
|
||||
wxWindow *parent = canvas->GetParent();
|
||||
while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
|
||||
parent = parent->GetParent();
|
||||
|
||||
if (parent)
|
||||
{
|
||||
event.SetEventType(wxEVT_CHAR_HOOK);
|
||||
if (parent->GetEventHandler()->ProcessEvent(event))
|
||||
return;
|
||||
}
|
||||
|
||||
// For simplicity, OnKeyDown is the same as OnChar
|
||||
// TODO: filter modifier key presses from OnChar
|
||||
event.SetEventType(wxEVT_KEY_DOWN);
|
||||
|
||||
// Only process OnChar if OnKeyDown didn't swallow it
|
||||
if (!canvas->GetEventHandler()->ProcessEvent (event))
|
||||
{
|
||||
event.SetEventType(wxEVT_CHAR);
|
||||
canvas->GetEventHandler()->ProcessEvent (event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KeyRelease:
|
||||
{
|
||||
KeySym keySym;
|
||||
(void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
|
||||
int id = wxCharCodeXToWX (keySym);
|
||||
|
||||
wxKeyEvent event (wxEVT_KEY_UP);
|
||||
|
||||
if (local_event.xkey.state & ShiftMask)
|
||||
event.m_shiftDown = TRUE;
|
||||
if (local_event.xkey.state & ControlMask)
|
||||
event.m_controlDown = TRUE;
|
||||
if (local_event.xkey.state & Mod3Mask)
|
||||
event.m_altDown = TRUE;
|
||||
if (local_event.xkey.state & Mod1Mask)
|
||||
event.m_metaDown = TRUE;
|
||||
event.SetEventObject(canvas);
|
||||
event.m_keyCode = id;
|
||||
event.SetTimestamp(local_event.xkey.time);
|
||||
|
||||
if (id > -1)
|
||||
{
|
||||
canvas->GetEventHandler()->ProcessEvent (event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FocusIn:
|
||||
{
|
||||
if (local_event.xfocus.detail != NotifyPointer)
|
||||
{
|
||||
wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
|
||||
event.SetEventObject(canvas);
|
||||
canvas->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FocusOut:
|
||||
{
|
||||
if (local_event.xfocus.detail != NotifyPointer)
|
||||
{
|
||||
wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
|
||||
event.SetEventObject(canvas);
|
||||
canvas->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wxPanelItemEventHandler(Widget wid,
|
||||
XtPointer WXUNUSED(client_data),
|
||||
XEvent* event,
|
||||
Boolean *continueToDispatch)
|
||||
{
|
||||
// Widget can be a label or the actual widget.
|
||||
|
||||
wxWindow *window = wxGetWindowFromTable(wid);
|
||||
if (window)
|
||||
{
|
||||
wxMouseEvent wxevent(0);
|
||||
if (wxTranslateMouseEvent(wxevent, window, wid, event))
|
||||
{
|
||||
window->GetEventHandler()->ProcessEvent(wxevent);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: probably the key to allowing default behaviour to happen. Say we
|
||||
// set a m_doDefault flag to FALSE at the start of this function. Then in
|
||||
// e.g. wxWindowX11::OnMouseEvent we can call Default() which sets this flag to
|
||||
// TRUE, indicating that default processing can happen. Thus, behaviour can
|
||||
// appear to be overridden just by adding an event handler and not calling
|
||||
// wxWindowX11::OnWhatever. ALSO, maybe we can use this instead of the current
|
||||
// way of handling drawing area events, to simplify things.
|
||||
*continueToDispatch = True;
|
||||
}
|
||||
|
||||
static void wxScrollBarCallback(Widget scrollbar,
|
||||
XtPointer clientData,
|
||||
XmScrollBarCallbackStruct *cbs)
|
||||
@@ -2043,43 +1634,8 @@ static void wxScrollBarCallback(Widget scrollbar,
|
||||
event.SetEventObject( win );
|
||||
win->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
|
||||
// For repainting arbitrary windows
|
||||
void wxUniversalRepaintProc(Widget w, XtPointer WXUNUSED(c_data), XEvent *event, char *)
|
||||
{
|
||||
Window window;
|
||||
Display *display;
|
||||
|
||||
wxWindow* win = wxGetWindowFromTable(w);
|
||||
if (!win)
|
||||
return;
|
||||
|
||||
switch(event -> type)
|
||||
{
|
||||
case Expose:
|
||||
{
|
||||
window = (Window) win -> GetXWindow();
|
||||
display = (Display *) win -> GetXDisplay();
|
||||
|
||||
if (event -> xexpose.count == 0)
|
||||
{
|
||||
win->DoPaint();
|
||||
|
||||
win->ClearUpdateRects();
|
||||
}
|
||||
else
|
||||
{
|
||||
win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
|
||||
event->xexpose.width, event->xexpose.height);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// 0
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CanvaseXXXSize() functions
|
||||
@@ -2291,28 +1847,31 @@ void wxWindowX11::CanvasGetPosition (int *x, int *y) const
|
||||
// TranslateXXXEvent() functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent)
|
||||
bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent)
|
||||
{
|
||||
// TODO
|
||||
#if 0
|
||||
switch (xevent->xany.type)
|
||||
{
|
||||
case EnterNotify: // never received here - yes ? MB
|
||||
case LeaveNotify: // never received here - yes ? MB
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
case MotionNotify:
|
||||
{
|
||||
wxEventType eventType = wxEVT_NULL;
|
||||
|
||||
// FIXME: this is never true I think - MB
|
||||
//
|
||||
if (xevent->xany.type == LeaveNotify)
|
||||
if (xevent->xany.type == EnterNotify)
|
||||
{
|
||||
win->SetButton1(FALSE);
|
||||
win->SetButton2(FALSE);
|
||||
win->SetButton3(FALSE);
|
||||
return FALSE;
|
||||
//if (local_event.xcrossing.mode!=NotifyNormal)
|
||||
// return ; // Ignore grab events
|
||||
eventType = wxEVT_ENTER_WINDOW;
|
||||
// canvas->GetEventHandler()->OnSetFocus();
|
||||
}
|
||||
else if (xevent->xany.type == LeaveNotify)
|
||||
{
|
||||
//if (local_event.xcrossingr.mode!=NotifyNormal)
|
||||
// return ; // Ignore grab events
|
||||
eventType = wxEVT_LEAVE_WINDOW;
|
||||
// canvas->GetEventHandler()->OnKillFocus();
|
||||
}
|
||||
else if (xevent->xany.type == MotionNotify)
|
||||
{
|
||||
@@ -2342,8 +1901,9 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget,
|
||||
}
|
||||
|
||||
// check for a double click
|
||||
//
|
||||
long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay());
|
||||
// TODO: where can we get this value from?
|
||||
//long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay());
|
||||
long dClickTime = 200;
|
||||
long ts = wxevent.GetTimestamp();
|
||||
|
||||
int buttonLast = win->GetLastClickedButton();
|
||||
@@ -2391,25 +1951,8 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget,
|
||||
|
||||
wxevent.SetEventType(eventType);
|
||||
|
||||
Position x1, y1;
|
||||
XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL);
|
||||
|
||||
int x2, y2;
|
||||
win->GetPosition(&x2, &y2);
|
||||
|
||||
// The button x/y must be translated to wxWindows
|
||||
// window space - the widget might be a label or button,
|
||||
// within a form.
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
if (widget != (Widget)win->GetMainWidget())
|
||||
{
|
||||
dx = x1;
|
||||
dy = y1;
|
||||
}
|
||||
|
||||
wxevent.m_x = xevent->xbutton.x + dx;
|
||||
wxevent.m_y = xevent->xbutton.y + dy;
|
||||
wxevent.m_x = xevent->xbutton.x;
|
||||
wxevent.m_y = xevent->xbutton.y;
|
||||
|
||||
wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
|
||||
|| (event_left_is_down (xevent)
|
||||
@@ -2432,7 +1975,6 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget,
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user