1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0032306: Draw Harness, ViewerTest - move window message processing to TKService

Aspect_WindowInputListener - basic mouse/keyboard/expose input methods
have been moved out from AIS_ViewController to dedicated base interface.

Added WNT_Window::ProcessMessage()/Xw_Window::ProcessMessage() methods
redirecting Win32/X11 message to Aspect_WindowInputListener.
This commit is contained in:
kgv
2021-04-16 13:01:17 +03:00
parent 1294d5e39e
commit e8e157df45
14 changed files with 1008 additions and 779 deletions

View File

@@ -18,7 +18,9 @@
#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <Aspect_Convert.hxx>
#include <Aspect_ScrollDelta.hxx>
#include <Aspect_WindowDefinitionError.hxx>
#include <Aspect_WindowInputListener.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
@@ -531,4 +533,168 @@ Aspect_VKey Xw_Window::VirtualKeyFromNative (unsigned long theKey)
return Aspect_VKey_UNKNOWN;
}
// =======================================================================
// function : ProcessMessage
// purpose :
// =======================================================================
bool Xw_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
XEvent& theMsg)
{
Display* aDisplay = myDisplay->GetDisplay();
// Handle event for the chosen display connection
switch (theMsg.type)
{
case ClientMessage:
{
if ((Atom)theMsg.xclient.data.l[0] == myDisplay->GetAtom (Aspect_XA_DELETE_WINDOW)
&& theMsg.xclient.window == myXWindow)
{
theListener.ProcessClose();
return true;
}
return false;
}
case FocusIn:
case FocusOut:
{
if (theMsg.xfocus.window == myXWindow)
{
theListener.ProcessFocus (theMsg.type == FocusIn);
}
return true;
}
case Expose:
{
if (theMsg.xexpose.window == myXWindow)
{
theListener.ProcessExpose();
}
// remove all the ExposureMask and process them at once
for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
{
if (!XCheckWindowEvent (aDisplay, myXWindow, ExposureMask, &theMsg))
{
break;
}
}
return true;
}
case ConfigureNotify:
{
// remove all the StructureNotifyMask and process them at once
for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
{
if (!XCheckWindowEvent (aDisplay, myXWindow, StructureNotifyMask, &theMsg))
{
break;
}
}
if (theMsg.xconfigure.window == myXWindow)
{
theListener.ProcessConfigure (true);
}
return true;
}
case KeyPress:
case KeyRelease:
{
XKeyEvent* aKeyEvent = (XKeyEvent* )&theMsg;
const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
if (aVKey != Aspect_VKey_UNKNOWN)
{
const double aTimeStamp = theListener.EventTime();
if (theMsg.type == KeyPress)
{
theListener.KeyDown (aVKey, aTimeStamp);
}
else
{
theListener.KeyUp (aVKey, aTimeStamp);
}
theListener.ProcessInput();
}
return true;
}
case ButtonPress:
case ButtonRelease:
{
const Graphic3d_Vec2i aPos (theMsg.xbutton.x, theMsg.xbutton.y);
Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
if (theMsg.xbutton.button == Button1) { aButton = Aspect_VKeyMouse_LeftButton; }
if (theMsg.xbutton.button == Button2) { aButton = Aspect_VKeyMouse_MiddleButton; }
if (theMsg.xbutton.button == Button3) { aButton = Aspect_VKeyMouse_RightButton; }
if ((theMsg.xbutton.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
if ((theMsg.xbutton.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
{
aFlags |= Aspect_VKeyFlags_ALT;
}
if (theMsg.xbutton.button == Button4
|| theMsg.xbutton.button == Button5)
{
if (theMsg.type != ButtonPress)
{
return true;
}
const double aDeltaF = (theMsg.xbutton.button == Button4 ? 1.0 : -1.0);
theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
}
else if (theMsg.type == ButtonPress)
{
theListener.PressMouseButton (aPos, aButton, aFlags, false);
}
else
{
theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
}
theListener.ProcessInput();
return true;
}
case MotionNotify:
{
if (theMsg.xmotion.window != myXWindow)
{
return false;
}
// remove all the ButtonMotionMask and process them at once
for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
{
if (!XCheckWindowEvent (aDisplay, myXWindow, ButtonMotionMask | PointerMotionMask, &theMsg))
{
break;
}
}
Graphic3d_Vec2i aPos (theMsg.xmotion.x, theMsg.xmotion.y);
Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
if ((theMsg.xmotion.state & Button1Mask) != 0) { aButtons |= Aspect_VKeyMouse_LeftButton; }
if ((theMsg.xmotion.state & Button2Mask) != 0) { aButtons |= Aspect_VKeyMouse_MiddleButton; }
if ((theMsg.xmotion.state & Button3Mask) != 0) { aButtons |= Aspect_VKeyMouse_RightButton; }
if ((theMsg.xmotion.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
if ((theMsg.xmotion.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
{
aFlags |= Aspect_VKeyFlags_ALT;
}
theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
theListener.ProcessInput();
return true;
}
}
return false;
}
#endif // Win32 or Mac OS X

View File

@@ -32,6 +32,7 @@
class Aspect_WindowDefinitionError;
class Aspect_WindowError;
class Aspect_WindowInputListener;
class Aspect_Background;
class Quantity_Color;
class Aspect_GradientBackground;
@@ -125,6 +126,13 @@ public:
//! for this working thread to avoid race conditions, since Xlib display connection is not thread-safe by default.
Standard_EXPORT virtual void InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp) Standard_OVERRIDE;
//! Process a single window message.
//! @param theListener [in][out] listener to redirect message
//! @param theMsg [in][out] message to process
//! @return TRUE if message has been processed
Standard_EXPORT virtual bool ProcessMessage (Aspect_WindowInputListener& theListener,
XEvent& theMsg);
protected:
Handle(Aspect_DisplayConnection) myDisplay; //!< X Display connection