mirror of https://github.com/buggins/dlangui.git
fix mouse processing
This commit is contained in:
parent
f1b4efe6eb
commit
5b358236f2
|
@ -113,7 +113,17 @@ class Window {
|
|||
protected Widget _mouseTrackingWidget;
|
||||
/// widget which tracks all events after processed ButtonDown
|
||||
protected Widget _mouseCaptureWidget;
|
||||
protected ushort _mouseCaptureButtons;
|
||||
protected bool _mouseCaptureFocusedOut;
|
||||
|
||||
protected bool dispatchCancel(MouseEvent event) {
|
||||
event.changeAction(MouseAction.Cancel);
|
||||
bool res = _mouseCaptureWidget.onMouseEvent(event);
|
||||
_mouseCaptureWidget = null;
|
||||
_mouseCaptureFocusedOut = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// dispatch mouse event to window content widgets
|
||||
bool dispatchMouseEvent(MouseEvent event) {
|
||||
// ignore events if there is no root
|
||||
|
@ -127,23 +137,29 @@ class Window {
|
|||
_mouseTrackingWidget = null;
|
||||
|
||||
bool res = false;
|
||||
ushort currentButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton);
|
||||
if (_mouseCaptureWidget !is null) {
|
||||
// try to forward message directly to active widget
|
||||
if (event.action == MouseAction.Move) {
|
||||
if (!_mouseCaptureWidget.isPointInside(event.x, event.y)) {
|
||||
if (currentButtons != _mouseCaptureButtons)
|
||||
return dispatchCancel(event);
|
||||
// point is no more inside of captured widget
|
||||
if (!_mouseCaptureFocusedOut) {
|
||||
// sending FocusOut message
|
||||
event.changeAction(MouseAction.FocusOut);
|
||||
_mouseCaptureFocusedOut = true;
|
||||
_mouseCaptureButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton);
|
||||
return _mouseCaptureWidget.onMouseEvent(event);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// point is inside widget
|
||||
if (_mouseCaptureFocusedOut) {
|
||||
event.changeAction(MouseAction.FocusIn); // back in after focus out
|
||||
_mouseCaptureFocusedOut = false;
|
||||
if (currentButtons != _mouseCaptureButtons)
|
||||
return dispatchCancel(event);
|
||||
event.changeAction(MouseAction.FocusIn); // back in after focus out
|
||||
}
|
||||
return _mouseCaptureWidget.onMouseEvent(event);
|
||||
}
|
||||
|
@ -152,6 +168,7 @@ class Window {
|
|||
// sending FocusOut message
|
||||
event.changeAction(MouseAction.FocusOut);
|
||||
_mouseCaptureFocusedOut = true;
|
||||
_mouseCaptureButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton);
|
||||
return _mouseCaptureWidget.onMouseEvent(event);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -34,24 +34,6 @@ version(linux) {
|
|||
Log.d("Destroying window");
|
||||
}
|
||||
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
|
||||
xcb_expose_event_t * event = cast(xcb_expose_event_t*)std.c.stdlib.malloc(xcb_expose_event_t.sizeof);
|
||||
event.response_type = XCB_EXPOSE; /* The type of the event, here it is XCB_EXPOSE */
|
||||
event.sequence = 0;
|
||||
event.window = _w; /* The Id of the window that receives the event (in case */
|
||||
/* our application registered for events on several windows */
|
||||
event.x = 0; /* The x coordinate of the top-left part of the window that needs to be redrawn */
|
||||
event.y = 0; /* The y coordinate of the top-left part of the window that needs to be redrawn */
|
||||
event.width = cast(ushort)_dx; /* The width of the part of the window that needs to be redrawn */
|
||||
event.height = cast(ushort)_dy; /* The height of the part of the window that needs to be redrawn */
|
||||
event.count = 1;
|
||||
|
||||
xcb_void_cookie_t res = xcb_send_event(_xcbconnection, false, _w, XCB_EVENT_MASK_EXPOSURE, cast(char *)event);
|
||||
xcb_flush(_xcbconnection);
|
||||
}
|
||||
|
||||
bool create() {
|
||||
uint mask;
|
||||
uint values[2];
|
||||
|
@ -209,10 +191,32 @@ version(linux) {
|
|||
}
|
||||
|
||||
ColorDrawBuf _drawbuf;
|
||||
bool _exposeSent;
|
||||
void processExpose(xcb_expose_event_t * event) {
|
||||
redraw();
|
||||
_exposeSent = false;
|
||||
}
|
||||
|
||||
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
if (_exposeSent)
|
||||
return;
|
||||
_exposeSent = true;
|
||||
xcb_expose_event_t * event = cast(xcb_expose_event_t*)std.c.stdlib.malloc(xcb_expose_event_t.sizeof);
|
||||
event.response_type = XCB_EXPOSE; /* The type of the event, here it is XCB_EXPOSE */
|
||||
event.sequence = 0;
|
||||
event.window = _w; /* The Id of the window that receives the event (in case */
|
||||
/* our application registered for events on several windows */
|
||||
event.x = 0; /* The x coordinate of the top-left part of the window that needs to be redrawn */
|
||||
event.y = 0; /* The y coordinate of the top-left part of the window that needs to be redrawn */
|
||||
event.width = cast(ushort)_dx; /* The width of the part of the window that needs to be redrawn */
|
||||
event.height = cast(ushort)_dy; /* The height of the part of the window that needs to be redrawn */
|
||||
event.count = 1;
|
||||
|
||||
xcb_void_cookie_t res = xcb_send_event(_xcbconnection, false, _w, XCB_EVENT_MASK_EXPOSURE, cast(char *)event);
|
||||
xcb_flush(_xcbconnection);
|
||||
}
|
||||
|
||||
protected ButtonDetails _lbutton;
|
||||
protected ButtonDetails _mbutton;
|
||||
protected ButtonDetails _rbutton;
|
||||
|
@ -238,14 +242,20 @@ version(linux) {
|
|||
case 1:
|
||||
button = MouseButton.Left;
|
||||
pbuttonDetails = &_lbutton;
|
||||
if (action == MouseAction.ButtonDown)
|
||||
flags |= MouseFlag.LButton;
|
||||
break;
|
||||
case 2:
|
||||
button = MouseButton.Middle;
|
||||
pbuttonDetails = &_mbutton;
|
||||
if (action == MouseAction.ButtonDown)
|
||||
flags |= MouseFlag.MButton;
|
||||
break;
|
||||
case 3:
|
||||
button = MouseButton.Right;
|
||||
pbuttonDetails = &_rbutton;
|
||||
if (action == MouseAction.ButtonDown)
|
||||
flags |= MouseFlag.RButton;
|
||||
break;
|
||||
case 4:
|
||||
if (action == MouseAction.ButtonUp)
|
||||
|
@ -464,8 +474,14 @@ version(linux) {
|
|||
}
|
||||
case XCB_LEAVE_NOTIFY: {
|
||||
xcb_leave_notify_event_t *leave = cast(xcb_leave_notify_event_t *)e;
|
||||
|
||||
Log.d("XCB_LEAVE_NOTIFY ", leave.event, " at coords ", leave.event_x, ", ", leave.event_y);
|
||||
Log.d("XCB_LEAVE_NOTIFY ", leave.event, " at coords ", leave.event_x, ", ", leave.event_y);
|
||||
XCBWindow window = getWindow(leave.event);
|
||||
if (window !is null) {
|
||||
//
|
||||
window.processMouseEvent(MouseAction.Leave, 0, leave.state, leave.event_x, leave.event_y);
|
||||
} else {
|
||||
Log.w("Received message for unknown window", leave.event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_PRESS: {
|
||||
|
|
|
@ -1,159 +1,159 @@
|
|||
module dlangui.widgets.controls;
|
||||
|
||||
import dlangui.widgets.widget;
|
||||
|
||||
/// static text widget
|
||||
class TextWidget : Widget {
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
styleId = "TEXT";
|
||||
}
|
||||
protected dstring _text;
|
||||
/// get widget text
|
||||
override @property dstring text() { return _text; }
|
||||
/// set text to show
|
||||
override @property Widget text(dstring s) {
|
||||
_text = s;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||
}
|
||||
|
||||
bool onClick() {
|
||||
// override it
|
||||
Log.d("Button.onClick ", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
override void onDraw(DrawBuf buf) {
|
||||
if (visibility != Visibility.Visible)
|
||||
return;
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
applyPadding(rc);
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
applyAlign(rc, sz);
|
||||
font.drawText(buf, rc.left, rc.top, text, textColor);
|
||||
}
|
||||
}
|
||||
|
||||
/// image widget
|
||||
class ImageWidget : Widget {
|
||||
|
||||
protected string _drawableId;
|
||||
protected DrawableRef _drawable;
|
||||
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
/// get drawable image id
|
||||
@property string drawableId() { return _drawableId; }
|
||||
/// set drawable image id
|
||||
@property ImageWidget drawableId(string id) {
|
||||
_drawableId = id;
|
||||
_drawable.clear();
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// get drawable
|
||||
@property ref DrawableRef drawable() {
|
||||
if (!_drawable.isNull)
|
||||
return _drawable;
|
||||
if (_drawableId !is null)
|
||||
_drawable = drawableCache.get(_drawableId);
|
||||
return _drawable;
|
||||
}
|
||||
/// set custom drawable (not one from resources)
|
||||
@property ImageWidget drawable(DrawableRef img) {
|
||||
_drawable = img;
|
||||
_drawableId = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
DrawableRef img = drawable;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
if (!img.isNull) {
|
||||
w = img.width;
|
||||
h = img.height;
|
||||
}
|
||||
measuredContent(parentWidth, parentHeight, w, h);
|
||||
}
|
||||
override void onDraw(DrawBuf buf) {
|
||||
if (visibility != Visibility.Visible)
|
||||
return;
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
applyPadding(rc);
|
||||
DrawableRef img = drawable;
|
||||
if (!img.isNull) {
|
||||
Point sz;
|
||||
sz.x = img.width;
|
||||
sz.y = img.height;
|
||||
applyAlign(rc, sz);
|
||||
img.drawTo(buf, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Button : Widget {
|
||||
protected dstring _text;
|
||||
override @property dstring text() { return _text; }
|
||||
override @property Widget text(dstring s) { _text = s; requestLayout(); return this; }
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
styleId = "BUTTON";
|
||||
}
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||
}
|
||||
override void onDraw(DrawBuf buf) {
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
buf.fillRect(_pos, backgroundColor);
|
||||
applyPadding(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
applyAlign(rc, sz);
|
||||
font.drawText(buf, rc.left, rc.top, text, textColor);
|
||||
}
|
||||
|
||||
override bool onMouseEvent(MouseEvent event) {
|
||||
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
|
||||
setState(State.Pressed);
|
||||
Log.d("Button state: ", state);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
|
||||
resetState(State.Pressed);
|
||||
Log.d("Button state: ", state);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.FocusOut) {
|
||||
resetState(State.Pressed);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.FocusIn) {
|
||||
setState(State.Pressed);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
module dlangui.widgets.controls;
|
||||
|
||||
import dlangui.widgets.widget;
|
||||
|
||||
/// static text widget
|
||||
class TextWidget : Widget {
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
styleId = "TEXT";
|
||||
}
|
||||
protected dstring _text;
|
||||
/// get widget text
|
||||
override @property dstring text() { return _text; }
|
||||
/// set text to show
|
||||
override @property Widget text(dstring s) {
|
||||
_text = s;
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||
}
|
||||
|
||||
bool onClick() {
|
||||
// override it
|
||||
Log.d("Button.onClick ", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
override void onDraw(DrawBuf buf) {
|
||||
if (visibility != Visibility.Visible)
|
||||
return;
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
applyPadding(rc);
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
applyAlign(rc, sz);
|
||||
font.drawText(buf, rc.left, rc.top, text, textColor);
|
||||
}
|
||||
}
|
||||
|
||||
/// image widget
|
||||
class ImageWidget : Widget {
|
||||
|
||||
protected string _drawableId;
|
||||
protected DrawableRef _drawable;
|
||||
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
/// get drawable image id
|
||||
@property string drawableId() { return _drawableId; }
|
||||
/// set drawable image id
|
||||
@property ImageWidget drawableId(string id) {
|
||||
_drawableId = id;
|
||||
_drawable.clear();
|
||||
requestLayout();
|
||||
return this;
|
||||
}
|
||||
/// get drawable
|
||||
@property ref DrawableRef drawable() {
|
||||
if (!_drawable.isNull)
|
||||
return _drawable;
|
||||
if (_drawableId !is null)
|
||||
_drawable = drawableCache.get(_drawableId);
|
||||
return _drawable;
|
||||
}
|
||||
/// set custom drawable (not one from resources)
|
||||
@property ImageWidget drawable(DrawableRef img) {
|
||||
_drawable = img;
|
||||
_drawableId = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
DrawableRef img = drawable;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
if (!img.isNull) {
|
||||
w = img.width;
|
||||
h = img.height;
|
||||
}
|
||||
measuredContent(parentWidth, parentHeight, w, h);
|
||||
}
|
||||
override void onDraw(DrawBuf buf) {
|
||||
if (visibility != Visibility.Visible)
|
||||
return;
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
applyPadding(rc);
|
||||
DrawableRef img = drawable;
|
||||
if (!img.isNull) {
|
||||
Point sz;
|
||||
sz.x = img.width;
|
||||
sz.y = img.height;
|
||||
applyAlign(rc, sz);
|
||||
img.drawTo(buf, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Button : Widget {
|
||||
protected dstring _text;
|
||||
override @property dstring text() { return _text; }
|
||||
override @property Widget text(dstring s) { _text = s; requestLayout(); return this; }
|
||||
this(string ID = null) {
|
||||
super(ID);
|
||||
styleId = "BUTTON";
|
||||
}
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||
}
|
||||
override void onDraw(DrawBuf buf) {
|
||||
super.onDraw(buf);
|
||||
Rect rc = _pos;
|
||||
applyMargins(rc);
|
||||
buf.fillRect(_pos, backgroundColor);
|
||||
applyPadding(rc);
|
||||
ClipRectSaver(buf, rc);
|
||||
FontRef font = font();
|
||||
Point sz = font.textSize(text);
|
||||
applyAlign(rc, sz);
|
||||
font.drawText(buf, rc.left, rc.top, text, textColor);
|
||||
}
|
||||
|
||||
override bool onMouseEvent(MouseEvent event) {
|
||||
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
|
||||
setState(State.Pressed);
|
||||
Log.d("Button state: ", state);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
|
||||
resetState(State.Pressed);
|
||||
Log.d("Button state: ", state);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.FocusOut || event.action == MouseAction.Cancel) {
|
||||
resetState(State.Pressed);
|
||||
return true;
|
||||
}
|
||||
if (event.action == MouseAction.FocusIn) {
|
||||
setState(State.Pressed);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue