fix mouse processing

This commit is contained in:
Vadim Lopatin 2014-03-18 11:45:33 +04:00
parent f1b4efe6eb
commit 5b358236f2
3 changed files with 214 additions and 181 deletions

View File

@ -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;

View File

@ -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: {

View File

@ -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;
}
}