|
|
|
@@ -25,6 +25,9 @@ |
|
|
|
|
|
|
|
extern Display* display;
|
|
|
|
extern XContext windowHandleXContext;
|
|
|
|
typedef void (*WindowMessageReceiveCallback) (XEvent&);
|
|
|
|
extern WindowMessageReceiveCallback dispatchWindowMessage;
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
struct Atoms
|
|
|
|
@@ -773,6 +776,7 @@ public: |
|
|
|
// it's dangerous to create a window on a thread other than the message thread..
|
|
|
|
jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager());
|
|
|
|
|
|
|
|
dispatchWindowMessage = windowMessageReceive;
|
|
|
|
repainter = new LinuxRepaintManager (this);
|
|
|
|
|
|
|
|
createWindow (parentToAddTo);
|
|
|
|
@@ -790,6 +794,21 @@ public: |
|
|
|
windowH = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// (this callback is hooked up in the messaging code)
|
|
|
|
static void windowMessageReceive (XEvent& event)
|
|
|
|
{
|
|
|
|
if (event.xany.window != None)
|
|
|
|
{
|
|
|
|
if (LinuxComponentPeer* const peer = getPeerFor (event.xany.window))
|
|
|
|
peer->handleWindowMessage (event);
|
|
|
|
}
|
|
|
|
else if (event.xany.type == KeymapNotify)
|
|
|
|
{
|
|
|
|
const XKeymapEvent& keymapEvent = (const XKeymapEvent&) event.xkeymap;
|
|
|
|
memcpy (Keys::keyStates, keymapEvent.key_vector, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void* getNativeHandle() const
|
|
|
|
{
|
|
|
|
@@ -1219,24 +1238,24 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void handleWindowMessage (XEvent* event)
|
|
|
|
void handleWindowMessage (XEvent& event)
|
|
|
|
{
|
|
|
|
switch (event->xany.type)
|
|
|
|
switch (event.xany.type)
|
|
|
|
{
|
|
|
|
case KeyPressEventType: handleKeyPressEvent ((XKeyEvent*) &event->xkey); break;
|
|
|
|
case KeyRelease: handleKeyReleaseEvent ((const XKeyEvent*) &event->xkey); break;
|
|
|
|
case ButtonPress: handleButtonPressEvent ((const XButtonPressedEvent*) &event->xbutton); break;
|
|
|
|
case ButtonRelease: handleButtonReleaseEvent ((const XButtonReleasedEvent*) &event->xbutton); break;
|
|
|
|
case MotionNotify: handleMotionNotifyEvent ((const XPointerMovedEvent*) &event->xmotion); break;
|
|
|
|
case EnterNotify: handleEnterNotifyEvent ((const XEnterWindowEvent*) &event->xcrossing); break;
|
|
|
|
case LeaveNotify: handleLeaveNotifyEvent ((const XLeaveWindowEvent*) &event->xcrossing); break;
|
|
|
|
case KeyPressEventType: handleKeyPressEvent (event.xkey); break;
|
|
|
|
case KeyRelease: handleKeyReleaseEvent (event.xkey); break;
|
|
|
|
case ButtonPress: handleButtonPressEvent (event.xbutton); break;
|
|
|
|
case ButtonRelease: handleButtonReleaseEvent (event.xbutton); break;
|
|
|
|
case MotionNotify: handleMotionNotifyEvent (event.xmotion); break;
|
|
|
|
case EnterNotify: handleEnterNotifyEvent (event.xcrossing); break;
|
|
|
|
case LeaveNotify: handleLeaveNotifyEvent (event.xcrossing); break;
|
|
|
|
case FocusIn: handleFocusInEvent(); break;
|
|
|
|
case FocusOut: handleFocusOutEvent(); break;
|
|
|
|
case Expose: handleExposeEvent ((XExposeEvent*) &event->xexpose); break;
|
|
|
|
case MappingNotify: handleMappingNotify ((XMappingEvent*) &event->xmapping); break;
|
|
|
|
case ClientMessage: handleClientMessageEvent ((XClientMessageEvent*) &event->xclient, event); break;
|
|
|
|
case Expose: handleExposeEvent (event.xexpose); break;
|
|
|
|
case MappingNotify: handleMappingNotify (event.xmapping); break;
|
|
|
|
case ClientMessage: handleClientMessageEvent (event.xclient, event); break;
|
|
|
|
case SelectionNotify: handleDragAndDropSelection (event); break;
|
|
|
|
case ConfigureNotify: handleConfigureNotifyEvent ((XConfigureEvent*) &event->xconfigure); break;
|
|
|
|
case ConfigureNotify: handleConfigureNotifyEvent (event.xconfigure); break;
|
|
|
|
case ReparentNotify: handleReparentNotifyEvent(); break;
|
|
|
|
case GravityNotify: handleGravityNotify(); break;
|
|
|
|
|
|
|
|
@@ -1263,7 +1282,7 @@ public: |
|
|
|
#if JUCE_USE_XSHM
|
|
|
|
{
|
|
|
|
ScopedXLock xlock;
|
|
|
|
if (event->xany.type == XShmGetEventBase (display))
|
|
|
|
if (event.xany.type == XShmGetEventBase (display))
|
|
|
|
repainter->notifyPaintCompleted();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
@@ -1271,7 +1290,7 @@ public: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleKeyPressEvent (XKeyEvent* const keyEvent)
|
|
|
|
void handleKeyPressEvent (XKeyEvent& keyEvent)
|
|
|
|
{
|
|
|
|
char utf8 [64] = { 0 };
|
|
|
|
juce_wchar unicodeChar = 0;
|
|
|
|
@@ -1281,18 +1300,18 @@ public: |
|
|
|
|
|
|
|
{
|
|
|
|
ScopedXLock xlock;
|
|
|
|
updateKeyStates (keyEvent->keycode, true);
|
|
|
|
updateKeyStates (keyEvent.keycode, true);
|
|
|
|
|
|
|
|
const char* oldLocale = ::setlocale (LC_ALL, 0);
|
|
|
|
::setlocale (LC_ALL, "");
|
|
|
|
XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0);
|
|
|
|
XLookupString (&keyEvent, utf8, sizeof (utf8), &sym, 0);
|
|
|
|
::setlocale (LC_ALL, oldLocale);
|
|
|
|
|
|
|
|
unicodeChar = *CharPointer_UTF8 (utf8);
|
|
|
|
keyCode = (int) unicodeChar;
|
|
|
|
|
|
|
|
if (keyCode < 0x20)
|
|
|
|
keyCode = XkbKeycodeToKeysym (display, keyEvent->keycode, 0, currentModifiers.isShiftDown() ? 1 : 0);
|
|
|
|
keyCode = XkbKeycodeToKeysym (display, keyEvent.keycode, 0, currentModifiers.isShiftDown() ? 1 : 0);
|
|
|
|
|
|
|
|
keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true);
|
|
|
|
}
|
|
|
|
@@ -1370,7 +1389,7 @@ public: |
|
|
|
handleKeyPress (keyCode, unicodeChar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isKeyReleasePartOfAutoRepeat (const XKeyEvent* const keyReleaseEvent)
|
|
|
|
static bool isKeyReleasePartOfAutoRepeat (const XKeyEvent& keyReleaseEvent)
|
|
|
|
{
|
|
|
|
if (XPending (display))
|
|
|
|
{
|
|
|
|
@@ -1379,23 +1398,23 @@ public: |
|
|
|
|
|
|
|
// Look for a subsequent key-down event with the same timestamp and keycode
|
|
|
|
return e.type == KeyPressEventType
|
|
|
|
&& e.xkey.keycode == keyReleaseEvent->keycode
|
|
|
|
&& e.xkey.time == keyReleaseEvent->time;
|
|
|
|
&& e.xkey.keycode == keyReleaseEvent.keycode
|
|
|
|
&& e.xkey.time == keyReleaseEvent.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleKeyReleaseEvent (const XKeyEvent* const keyEvent)
|
|
|
|
void handleKeyReleaseEvent (const XKeyEvent& keyEvent)
|
|
|
|
{
|
|
|
|
if (! isKeyReleasePartOfAutoRepeat (keyEvent))
|
|
|
|
{
|
|
|
|
updateKeyStates (keyEvent->keycode, false);
|
|
|
|
updateKeyStates (keyEvent.keycode, false);
|
|
|
|
KeySym sym;
|
|
|
|
|
|
|
|
{
|
|
|
|
ScopedXLock xlock;
|
|
|
|
sym = XkbKeycodeToKeysym (display, keyEvent->keycode, 0, 0);
|
|
|
|
sym = XkbKeycodeToKeysym (display, keyEvent.keycode, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ModifierKeys oldMods (currentModifiers);
|
|
|
|
@@ -1409,7 +1428,13 @@ public: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleWheelEvent (const XButtonPressedEvent* const buttonPressEvent, const float amount)
|
|
|
|
template <typename EventType>
|
|
|
|
static Point<int> getMousePos (const EventType& e) noexcept
|
|
|
|
{
|
|
|
|
return Point<int> (e.x, e.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleWheelEvent (const XButtonPressedEvent& buttonPressEvent, const float amount)
|
|
|
|
{
|
|
|
|
MouseWheelDetails wheel;
|
|
|
|
wheel.deltaX = 0.0f;
|
|
|
|
@@ -1417,23 +1442,21 @@ public: |
|
|
|
wheel.isReversed = false;
|
|
|
|
wheel.isSmooth = false;
|
|
|
|
|
|
|
|
handleMouseWheel (0, Point<int> (buttonPressEvent->x, buttonPressEvent->y),
|
|
|
|
getEventTime (buttonPressEvent->time), wheel);
|
|
|
|
handleMouseWheel (0, getMousePos (buttonPressEvent), getEventTime (buttonPressEvent), wheel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleButtonPressEvent (const XButtonPressedEvent* const buttonPressEvent, int buttonModifierFlag)
|
|
|
|
void handleButtonPressEvent (const XButtonPressedEvent& buttonPressEvent, int buttonModifierFlag)
|
|
|
|
{
|
|
|
|
currentModifiers = currentModifiers.withFlags (buttonModifierFlag);
|
|
|
|
toFront (true);
|
|
|
|
handleMouseEvent (0, Point<int> (buttonPressEvent->x, buttonPressEvent->y), currentModifiers,
|
|
|
|
getEventTime (buttonPressEvent->time));
|
|
|
|
handleMouseEvent (0, getMousePos (buttonPressEvent), currentModifiers, getEventTime (buttonPressEvent));
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleButtonPressEvent (const XButtonPressedEvent* const buttonPressEvent)
|
|
|
|
void handleButtonPressEvent (const XButtonPressedEvent& buttonPressEvent)
|
|
|
|
{
|
|
|
|
updateKeyModifiers (buttonPressEvent->state);
|
|
|
|
updateKeyModifiers (buttonPressEvent.state);
|
|
|
|
|
|
|
|
switch (pointerMap [buttonPressEvent->button - Button1])
|
|
|
|
switch (pointerMap [buttonPressEvent.button - Button1])
|
|
|
|
{
|
|
|
|
case Keys::WheelUp: handleWheelEvent (buttonPressEvent, 50.0f / 256.0f); break;
|
|
|
|
case Keys::WheelDown: handleWheelEvent (buttonPressEvent, -50.0f / 256.0f); break;
|
|
|
|
@@ -1446,11 +1469,11 @@ public: |
|
|
|
clearLastMousePos();
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleButtonReleaseEvent (const XButtonReleasedEvent* const buttonRelEvent)
|
|
|
|
void handleButtonReleaseEvent (const XButtonReleasedEvent& buttonRelEvent)
|
|
|
|
{
|
|
|
|
updateKeyModifiers (buttonRelEvent->state);
|
|
|
|
updateKeyModifiers (buttonRelEvent.state);
|
|
|
|
|
|
|
|
switch (pointerMap [buttonRelEvent->button - Button1])
|
|
|
|
switch (pointerMap [buttonRelEvent.button - Button1])
|
|
|
|
{
|
|
|
|
case Keys::LeftButton: currentModifiers = currentModifiers.withoutFlags (ModifierKeys::leftButtonModifier); break;
|
|
|
|
case Keys::RightButton: currentModifiers = currentModifiers.withoutFlags (ModifierKeys::rightButtonModifier); break;
|
|
|
|
@@ -1458,16 +1481,15 @@ public: |
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
handleMouseEvent (0, Point<int> (buttonRelEvent->x, buttonRelEvent->y), currentModifiers,
|
|
|
|
getEventTime (buttonRelEvent->time));
|
|
|
|
handleMouseEvent (0, getMousePos (buttonRelEvent), currentModifiers, getEventTime (buttonRelEvent));
|
|
|
|
|
|
|
|
clearLastMousePos();
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleMotionNotifyEvent (const XPointerMovedEvent* const movedEvent)
|
|
|
|
void handleMotionNotifyEvent (const XPointerMovedEvent& movedEvent)
|
|
|
|
{
|
|
|
|
updateKeyModifiers (movedEvent->state);
|
|
|
|
const Point<int> mousePos (movedEvent->x_root, movedEvent->y_root);
|
|
|
|
updateKeyModifiers (movedEvent.state);
|
|
|
|
const Point<int> mousePos (movedEvent.x_root, movedEvent.y_root);
|
|
|
|
|
|
|
|
if (lastMousePos != mousePos)
|
|
|
|
{
|
|
|
|
@@ -1497,31 +1519,31 @@ public: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleMouseEvent (0, mousePos - getScreenPosition(), currentModifiers, getEventTime (movedEvent->time));
|
|
|
|
handleMouseEvent (0, mousePos - getScreenPosition(), currentModifiers, getEventTime (movedEvent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleEnterNotifyEvent (const XEnterWindowEvent* const enterEvent)
|
|
|
|
void handleEnterNotifyEvent (const XEnterWindowEvent& enterEvent)
|
|
|
|
{
|
|
|
|
clearLastMousePos();
|
|
|
|
|
|
|
|
if (! currentModifiers.isAnyMouseButtonDown())
|
|
|
|
{
|
|
|
|
updateKeyModifiers (enterEvent->state);
|
|
|
|
handleMouseEvent (0, Point<int> (enterEvent->x, enterEvent->y), currentModifiers, getEventTime (enterEvent->time));
|
|
|
|
updateKeyModifiers (enterEvent.state);
|
|
|
|
handleMouseEvent (0, getMousePos (enterEvent), currentModifiers, getEventTime (enterEvent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleLeaveNotifyEvent (const XLeaveWindowEvent* const leaveEvent)
|
|
|
|
void handleLeaveNotifyEvent (const XLeaveWindowEvent& leaveEvent)
|
|
|
|
{
|
|
|
|
// Suppress the normal leave if we've got a pointer grab, or if
|
|
|
|
// it's a bogus one caused by clicking a mouse button when running
|
|
|
|
// in a Window manager
|
|
|
|
if (((! currentModifiers.isAnyMouseButtonDown()) && leaveEvent->mode == NotifyNormal)
|
|
|
|
|| leaveEvent->mode == NotifyUngrab)
|
|
|
|
if (((! currentModifiers.isAnyMouseButtonDown()) && leaveEvent.mode == NotifyNormal)
|
|
|
|
|| leaveEvent.mode == NotifyUngrab)
|
|
|
|
{
|
|
|
|
updateKeyModifiers (leaveEvent->state);
|
|
|
|
handleMouseEvent (0, Point<int> (leaveEvent->x, leaveEvent->y), currentModifiers, getEventTime (leaveEvent->time));
|
|
|
|
updateKeyModifiers (leaveEvent.state);
|
|
|
|
handleMouseEvent (0, getMousePos (leaveEvent), currentModifiers, getEventTime (leaveEvent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1539,37 +1561,37 @@ public: |
|
|
|
handleFocusLoss();
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleExposeEvent (XExposeEvent* exposeEvent)
|
|
|
|
void handleExposeEvent (XExposeEvent& exposeEvent)
|
|
|
|
{
|
|
|
|
// Batch together all pending expose events
|
|
|
|
XEvent nextEvent;
|
|
|
|
ScopedXLock xlock;
|
|
|
|
|
|
|
|
if (exposeEvent->window != windowH)
|
|
|
|
if (exposeEvent.window != windowH)
|
|
|
|
{
|
|
|
|
Window child;
|
|
|
|
XTranslateCoordinates (display, exposeEvent->window, windowH,
|
|
|
|
exposeEvent->x, exposeEvent->y, &exposeEvent->x, &exposeEvent->y,
|
|
|
|
XTranslateCoordinates (display, exposeEvent.window, windowH,
|
|
|
|
exposeEvent.x, exposeEvent.y, &exposeEvent.x, &exposeEvent.y,
|
|
|
|
&child);
|
|
|
|
}
|
|
|
|
|
|
|
|
repaint (Rectangle<int> (exposeEvent->x, exposeEvent->y,
|
|
|
|
exposeEvent->width, exposeEvent->height));
|
|
|
|
repaint (Rectangle<int> (exposeEvent.x, exposeEvent.y,
|
|
|
|
exposeEvent.width, exposeEvent.height));
|
|
|
|
|
|
|
|
while (XEventsQueued (display, QueuedAfterFlush) > 0)
|
|
|
|
{
|
|
|
|
XPeekEvent (display, &nextEvent);
|
|
|
|
if (nextEvent.type != Expose || nextEvent.xany.window != exposeEvent->window)
|
|
|
|
if (nextEvent.type != Expose || nextEvent.xany.window != exposeEvent.window)
|
|
|
|
break;
|
|
|
|
|
|
|
|
XNextEvent (display, &nextEvent);
|
|
|
|
XExposeEvent* nextExposeEvent = (XExposeEvent*) &nextEvent.xexpose;
|
|
|
|
repaint (Rectangle<int> (nextExposeEvent->x, nextExposeEvent->y,
|
|
|
|
nextExposeEvent->width, nextExposeEvent->height));
|
|
|
|
const XExposeEvent& nextExposeEvent = (const XExposeEvent&) nextEvent.xexpose;
|
|
|
|
repaint (Rectangle<int> (nextExposeEvent.x, nextExposeEvent.y,
|
|
|
|
nextExposeEvent.width, nextExposeEvent.height));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleConfigureNotifyEvent (XConfigureEvent* const confEvent)
|
|
|
|
void handleConfigureNotifyEvent (XConfigureEvent& confEvent)
|
|
|
|
{
|
|
|
|
updateBounds();
|
|
|
|
updateBorderSize();
|
|
|
|
@@ -1585,8 +1607,8 @@ public: |
|
|
|
currentModalComp->inputAttemptWhenModal();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (confEvent->window == windowH
|
|
|
|
&& confEvent->above != 0
|
|
|
|
if (confEvent.window == windowH
|
|
|
|
&& confEvent.above != 0
|
|
|
|
&& isFrontWindow())
|
|
|
|
{
|
|
|
|
handleBroughtToFront();
|
|
|
|
@@ -1618,32 +1640,32 @@ public: |
|
|
|
handleMovedOrResized();
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleMappingNotify (XMappingEvent* const mappingEvent)
|
|
|
|
void handleMappingNotify (XMappingEvent& mappingEvent)
|
|
|
|
{
|
|
|
|
if (mappingEvent->request != MappingPointer)
|
|
|
|
if (mappingEvent.request != MappingPointer)
|
|
|
|
{
|
|
|
|
// Deal with modifier/keyboard mapping
|
|
|
|
ScopedXLock xlock;
|
|
|
|
XRefreshKeyboardMapping (mappingEvent);
|
|
|
|
XRefreshKeyboardMapping (&mappingEvent);
|
|
|
|
updateModifierMappings();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleClientMessageEvent (XClientMessageEvent* const clientMsg, XEvent* event)
|
|
|
|
void handleClientMessageEvent (XClientMessageEvent& clientMsg, XEvent& event)
|
|
|
|
{
|
|
|
|
const Atoms& atoms = Atoms::get();
|
|
|
|
|
|
|
|
if (clientMsg->message_type == atoms.Protocols && clientMsg->format == 32)
|
|
|
|
if (clientMsg.message_type == atoms.Protocols && clientMsg.format == 32)
|
|
|
|
{
|
|
|
|
const Atom atom = (Atom) clientMsg->data.l[0];
|
|
|
|
const Atom atom = (Atom) clientMsg.data.l[0];
|
|
|
|
|
|
|
|
if (atom == atoms.ProtocolList [Atoms::PING])
|
|
|
|
{
|
|
|
|
Window root = RootWindow (display, DefaultScreen (display));
|
|
|
|
|
|
|
|
clientMsg->window = root;
|
|
|
|
clientMsg.window = root;
|
|
|
|
|
|
|
|
XSendEvent (display, root, False, NoEventMask, event);
|
|
|
|
XSendEvent (display, root, False, NoEventMask, &event);
|
|
|
|
XFlush (display);
|
|
|
|
}
|
|
|
|
else if (atom == atoms.ProtocolList [Atoms::TAKE_FOCUS])
|
|
|
|
@@ -1653,11 +1675,11 @@ public: |
|
|
|
XWindowAttributes atts;
|
|
|
|
|
|
|
|
ScopedXLock xlock;
|
|
|
|
if (clientMsg->window != 0
|
|
|
|
&& XGetWindowAttributes (display, clientMsg->window, &atts))
|
|
|
|
if (clientMsg.window != 0
|
|
|
|
&& XGetWindowAttributes (display, clientMsg.window, &atts))
|
|
|
|
{
|
|
|
|
if (atts.map_state == IsViewable)
|
|
|
|
XSetInputFocus (display, clientMsg->window, RevertToParent, clientMsg->data.l[1]);
|
|
|
|
XSetInputFocus (display, clientMsg.window, RevertToParent, clientMsg.data.l[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -1666,27 +1688,27 @@ public: |
|
|
|
handleUserClosingWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndEnter)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndEnter)
|
|
|
|
{
|
|
|
|
handleDragAndDropEnter (clientMsg);
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndLeave)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndLeave)
|
|
|
|
{
|
|
|
|
resetDragAndDrop();
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndPosition)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndPosition)
|
|
|
|
{
|
|
|
|
handleDragAndDropPosition (clientMsg);
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndDrop)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndDrop)
|
|
|
|
{
|
|
|
|
handleDragAndDropDrop (clientMsg);
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndStatus)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndStatus)
|
|
|
|
{
|
|
|
|
handleDragAndDropStatus (clientMsg);
|
|
|
|
}
|
|
|
|
else if (clientMsg->message_type == atoms.XdndFinished)
|
|
|
|
else if (clientMsg.message_type == atoms.XdndFinished)
|
|
|
|
{
|
|
|
|
resetDragAndDrop();
|
|
|
|
}
|
|
|
|
@@ -1904,19 +1926,13 @@ private: |
|
|
|
switch (sym)
|
|
|
|
{
|
|
|
|
case XK_Shift_L:
|
|
|
|
case XK_Shift_R:
|
|
|
|
modifier = ModifierKeys::shiftModifier;
|
|
|
|
break;
|
|
|
|
case XK_Shift_R: modifier = ModifierKeys::shiftModifier; break;
|
|
|
|
|
|
|
|
case XK_Control_L:
|
|
|
|
case XK_Control_R:
|
|
|
|
modifier = ModifierKeys::ctrlModifier;
|
|
|
|
break;
|
|
|
|
case XK_Control_R: modifier = ModifierKeys::ctrlModifier; break;
|
|
|
|
|
|
|
|
case XK_Alt_L:
|
|
|
|
case XK_Alt_R:
|
|
|
|
modifier = ModifierKeys::altModifier;
|
|
|
|
break;
|
|
|
|
case XK_Alt_R: modifier = ModifierKeys::altModifier; break;
|
|
|
|
|
|
|
|
case XK_Num_Lock:
|
|
|
|
if (press)
|
|
|
|
@@ -1955,9 +1971,7 @@ private: |
|
|
|
Keys::AltMask = 0;
|
|
|
|
Keys::NumLockMask = 0;
|
|
|
|
|
|
|
|
XModifierKeymap* mapping = XGetModifierMapping (display);
|
|
|
|
|
|
|
|
if (mapping)
|
|
|
|
if (XModifierKeymap* const mapping = XGetModifierMapping (display))
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
@@ -2213,6 +2227,12 @@ private: |
|
|
|
| ExposureMask | StructureNotifyMask | FocusChangeMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename EventType>
|
|
|
|
static int64 getEventTime (const EventType& t)
|
|
|
|
{
|
|
|
|
return getEventTime (t.time);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int64 getEventTime (::Time t)
|
|
|
|
{
|
|
|
|
static int64 eventTimeOffset = 0x12345678;
|
|
|
|
@@ -2322,9 +2342,9 @@ private: |
|
|
|
sendDragAndDropMessage (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDragAndDropStatus (const XClientMessageEvent* const clientMsg)
|
|
|
|
void handleDragAndDropStatus (const XClientMessageEvent& clientMsg)
|
|
|
|
{
|
|
|
|
if ((clientMsg->data.l[1] & 1) == 0)
|
|
|
|
if ((clientMsg.data.l[1] & 1) == 0)
|
|
|
|
{
|
|
|
|
sendDragAndDropLeave();
|
|
|
|
|
|
|
|
@@ -2335,15 +2355,15 @@ private: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDragAndDropPosition (const XClientMessageEvent* const clientMsg)
|
|
|
|
void handleDragAndDropPosition (const XClientMessageEvent& clientMsg)
|
|
|
|
{
|
|
|
|
if (dragAndDropSourceWindow == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dragAndDropSourceWindow = clientMsg->data.l[0];
|
|
|
|
dragAndDropSourceWindow = clientMsg.data.l[0];
|
|
|
|
|
|
|
|
Point<int> dropPos ((int) clientMsg->data.l[2] >> 16,
|
|
|
|
(int) clientMsg->data.l[2] & 0xffff);
|
|
|
|
Point<int> dropPos ((int) clientMsg.data.l[2] >> 16,
|
|
|
|
(int) clientMsg.data.l[2] & 0xffff);
|
|
|
|
dropPos -= getScreenPosition();
|
|
|
|
|
|
|
|
if (dragInfo.position != dropPos)
|
|
|
|
@@ -2355,7 +2375,7 @@ private: |
|
|
|
|
|
|
|
for (int i = numElementsInArray (atoms.allowedActions); --i >= 0;)
|
|
|
|
{
|
|
|
|
if ((Atom) clientMsg->data.l[4] == atoms.allowedActions[i])
|
|
|
|
if ((Atom) clientMsg.data.l[4] == atoms.allowedActions[i])
|
|
|
|
{
|
|
|
|
targetAction = atoms.allowedActions[i];
|
|
|
|
break;
|
|
|
|
@@ -2372,7 +2392,7 @@ private: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDragAndDropDrop (const XClientMessageEvent* const clientMsg)
|
|
|
|
void handleDragAndDropDrop (const XClientMessageEvent& clientMsg)
|
|
|
|
{
|
|
|
|
if (dragInfo.files.size() == 0)
|
|
|
|
updateDraggedFileList (clientMsg);
|
|
|
|
@@ -2386,13 +2406,13 @@ private: |
|
|
|
handleDragDrop (dragInfoCopy);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDragAndDropEnter (const XClientMessageEvent* const clientMsg)
|
|
|
|
void handleDragAndDropEnter (const XClientMessageEvent& clientMsg)
|
|
|
|
{
|
|
|
|
dragInfo.files.clear();
|
|
|
|
srcMimeTypeAtomList.clear();
|
|
|
|
|
|
|
|
dragAndDropCurrentMimeType = 0;
|
|
|
|
const unsigned long dndCurrentVersion = static_cast <unsigned long> (clientMsg->data.l[1] & 0xff000000) >> 24;
|
|
|
|
const unsigned long dndCurrentVersion = static_cast <unsigned long> (clientMsg.data.l[1] & 0xff000000) >> 24;
|
|
|
|
|
|
|
|
if (dndCurrentVersion < 3 || dndCurrentVersion > Atoms::DndVersion)
|
|
|
|
{
|
|
|
|
@@ -2400,9 +2420,9 @@ private: |
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dragAndDropSourceWindow = clientMsg->data.l[0];
|
|
|
|
dragAndDropSourceWindow = clientMsg.data.l[0];
|
|
|
|
|
|
|
|
if ((clientMsg->data.l[1] & 1) != 0)
|
|
|
|
if ((clientMsg.data.l[1] & 1) != 0)
|
|
|
|
{
|
|
|
|
ScopedXLock xlock;
|
|
|
|
GetXProperty prop (dragAndDropSourceWindow, Atoms::get().XdndTypeList, 0, 0x8000000L, false, XA_ATOM);
|
|
|
|
@@ -2423,8 +2443,8 @@ private: |
|
|
|
if (srcMimeTypeAtomList.size() == 0)
|
|
|
|
{
|
|
|
|
for (int i = 2; i < 5; ++i)
|
|
|
|
if (clientMsg->data.l[i] != None)
|
|
|
|
srcMimeTypeAtomList.add (clientMsg->data.l[i]);
|
|
|
|
if (clientMsg.data.l[i] != None)
|
|
|
|
srcMimeTypeAtomList.add (clientMsg.data.l[i]);
|
|
|
|
|
|
|
|
if (srcMimeTypeAtomList.size() == 0)
|
|
|
|
{
|
|
|
|
@@ -2442,11 +2462,11 @@ private: |
|
|
|
handleDragAndDropPosition (clientMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDragAndDropSelection (const XEvent* const evt)
|
|
|
|
void handleDragAndDropSelection (const XEvent& evt)
|
|
|
|
{
|
|
|
|
dragInfo.files.clear();
|
|
|
|
|
|
|
|
if (evt->xselection.property != 0)
|
|
|
|
if (evt.xselection.property != 0)
|
|
|
|
{
|
|
|
|
StringArray lines;
|
|
|
|
|
|
|
|
@@ -2455,7 +2475,7 @@ private: |
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
GetXProperty prop (evt->xany.window, evt->xselection.property,
|
|
|
|
GetXProperty prop (evt.xany.window, evt.xselection.property,
|
|
|
|
dropData.getSize() / 4, 65536, true, AnyPropertyType);
|
|
|
|
|
|
|
|
if (! prop.success)
|
|
|
|
@@ -2478,7 +2498,7 @@ private: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateDraggedFileList (const XClientMessageEvent* const clientMsg)
|
|
|
|
void updateDraggedFileList (const XClientMessageEvent& clientMsg)
|
|
|
|
{
|
|
|
|
dragInfo.files.clear();
|
|
|
|
|
|
|
|
@@ -2491,7 +2511,7 @@ private: |
|
|
|
dragAndDropCurrentMimeType,
|
|
|
|
Atoms::getCreating ("JXSelectionWindowProperty"),
|
|
|
|
windowH,
|
|
|
|
clientMsg->data.l[2]);
|
|
|
|
clientMsg.data.l[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2592,23 +2612,6 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAtt |
|
|
|
return new LinuxComponentPeer (*this, styleFlags, (Window) nativeWindowToAttachTo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
// (this callback is hooked up in the messaging code)
|
|
|
|
void juce_windowMessageReceive (XEvent* event)
|
|
|
|
{
|
|
|
|
if (event->xany.window != None)
|
|
|
|
{
|
|
|
|
if (LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (event->xany.window))
|
|
|
|
peer->handleWindowMessage (event);
|
|
|
|
}
|
|
|
|
else if (event->xany.type == KeymapNotify)
|
|
|
|
{
|
|
|
|
const XKeymapEvent* const keymapEvent = (const XKeymapEvent*) &event->xkeymap;
|
|
|
|
memcpy (Keys::keyStates, keymapEvent->key_vector, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void Desktop::Displays::findDisplays()
|
|
|
|
{
|
|
|
|
|