mirror of https://github.com/buggins/dlangui.git
fix 9patch detection; mouse support under XCB
This commit is contained in:
parent
67b4534b70
commit
f1b4efe6eb
|
@ -20,7 +20,8 @@ enum MouseFlag : ushort {
|
|||
RButton = 0x0002,
|
||||
Shift = 0x0004,
|
||||
XButton1= 0x0020,
|
||||
XButton2= 0x0040
|
||||
XButton2= 0x0040,
|
||||
Alt = 0x0080
|
||||
}
|
||||
|
||||
/// mouse button state details
|
||||
|
|
|
@ -332,7 +332,7 @@ class ColorDrawBufBase : DrawBuf {
|
|||
x0 = 0;
|
||||
x1 = 0;
|
||||
for (int x = 1; x < _dx - 1; x++) {
|
||||
if (line[x] == 0x00000000) { // opaque black pixel
|
||||
if (isBlackPixel(line[x])) { // opaque black pixel
|
||||
if (!foundUsed) {
|
||||
x0 = x;
|
||||
foundUsed = true;
|
||||
|
@ -343,6 +343,18 @@ class ColorDrawBufBase : DrawBuf {
|
|||
return x1 > x0;
|
||||
}
|
||||
|
||||
static bool isBlackPixel(uint c) {
|
||||
if (((c >> 24) & 255) > 10)
|
||||
return false;
|
||||
if (((c >> 16) & 255) > 10)
|
||||
return false;
|
||||
if (((c >> 8) & 255) > 10)
|
||||
return false;
|
||||
if (((c >> 0) & 255) > 10)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// detect position of black pixels in column for 9-patch markup
|
||||
private bool detectVLine(int x, ref int y0, ref int y1) {
|
||||
bool foundUsed = false;
|
||||
|
@ -350,7 +362,7 @@ class ColorDrawBufBase : DrawBuf {
|
|||
y1 = 0;
|
||||
for (int y = 1; y < _dy - 1; y++) {
|
||||
uint * line = scanLine(y);
|
||||
if (line[x] == 0x00000000) { // opaque black pixel
|
||||
if (isBlackPixel(line[x])) { // opaque black pixel
|
||||
if (!foundUsed) {
|
||||
y0 = y;
|
||||
foundUsed = true;
|
||||
|
@ -374,14 +386,15 @@ class ColorDrawBufBase : DrawBuf {
|
|||
return false; // no black pixels on 1-pixel frame
|
||||
NinePatch * p = new NinePatch();
|
||||
p.frame.left = x00 - 1;
|
||||
p.frame.right = _dy - y01 - 1;
|
||||
p.frame.right = _dx - x01 - 1;
|
||||
p.frame.top = y00 - 1;
|
||||
p.frame.bottom = _dy - y01 - 1;
|
||||
p.padding.left = x10 - 1;
|
||||
p.padding.right = _dy - y11 - 1;
|
||||
p.padding.right = _dx - x11 - 1;
|
||||
p.padding.top = y10 - 1;
|
||||
p.padding.bottom = _dy - y11 - 1;
|
||||
_ninePatch = p;
|
||||
//Log.d("NinePatch detected: frame=", p.frame, " padding=", p.padding, " left+right=", p.frame.left + p.frame.right, " dx=", _dx);
|
||||
return true;
|
||||
}
|
||||
override void drawGlyph(int x, int y, Glyph * glyph, uint color) {
|
||||
|
@ -706,7 +719,7 @@ class ImageDrawable : Drawable {
|
|||
}
|
||||
private static void correctFrameBounds(ref int n1, ref int n2, ref int n3, ref int n4) {
|
||||
if (n1 > n2) {
|
||||
assert(n2 - n1 == n4 - n3);
|
||||
//assert(n2 - n1 == n4 - n3);
|
||||
int middledist = (n1 + n2) / 2 - n1;
|
||||
n1 = n2 = n1 + middledist;
|
||||
n3 = n4 = n3 + middledist;
|
||||
|
|
|
@ -385,7 +385,7 @@ class Win32Window : Window {
|
|||
}
|
||||
if (action == MouseAction.ButtonDown) {
|
||||
pbuttonDetails.down(x, y, cast(ushort)flags);
|
||||
} else if (action == MouseAction.ButtonDown) {
|
||||
} else if (action == MouseAction.ButtonUp) {
|
||||
pbuttonDetails.up(x, y, cast(ushort)flags);
|
||||
}
|
||||
if (((message == WM_MOUSELEAVE) || (x < 0 || y < 0 || x > _dx || y > _dy)) && _mouseTracking) {
|
||||
|
|
|
@ -13,6 +13,7 @@ version(linux) {
|
|||
import std.conv;
|
||||
|
||||
import dlangui.core.logger;
|
||||
import dlangui.core.events;
|
||||
import dlangui.graphics.drawbuf;
|
||||
import dlangui.graphics.fonts;
|
||||
import dlangui.graphics.ftfonts;
|
||||
|
@ -35,7 +36,20 @@ version(linux) {
|
|||
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
redraw();
|
||||
|
||||
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() {
|
||||
|
@ -199,6 +213,74 @@ version(linux) {
|
|||
redraw();
|
||||
}
|
||||
|
||||
protected ButtonDetails _lbutton;
|
||||
protected ButtonDetails _mbutton;
|
||||
protected ButtonDetails _rbutton;
|
||||
void processMouseEvent(MouseAction action, ubyte detail, ushort state, short x, short y) {
|
||||
MouseButton button = MouseButton.None;
|
||||
short wheelDelta = 0;
|
||||
ButtonDetails * pbuttonDetails = null;
|
||||
ushort flags = 0;
|
||||
if (state & XCB_BUTTON_MASK_1)
|
||||
flags |= MouseFlag.LButton;
|
||||
if (state & XCB_BUTTON_MASK_2)
|
||||
flags |= MouseFlag.MButton;
|
||||
if (state & XCB_BUTTON_MASK_3)
|
||||
flags |= MouseFlag.RButton;
|
||||
if (state & XCB_MOD_MASK_SHIFT)
|
||||
flags |= MouseFlag.Shift;
|
||||
if (state & XCB_MOD_MASK_CONTROL)
|
||||
flags |= MouseFlag.Control;
|
||||
if (state & XCB_MOD_MASK_LOCK)
|
||||
flags |= MouseFlag.Alt;
|
||||
if (action == MouseAction.ButtonDown || action == MouseAction.ButtonUp) {
|
||||
switch (detail) {
|
||||
case 1:
|
||||
button = MouseButton.Left;
|
||||
pbuttonDetails = &_lbutton;
|
||||
break;
|
||||
case 2:
|
||||
button = MouseButton.Middle;
|
||||
pbuttonDetails = &_mbutton;
|
||||
break;
|
||||
case 3:
|
||||
button = MouseButton.Right;
|
||||
pbuttonDetails = &_rbutton;
|
||||
break;
|
||||
case 4:
|
||||
if (action == MouseAction.ButtonUp)
|
||||
return;
|
||||
wheelDelta = -1;
|
||||
action = MouseAction.Wheel;
|
||||
break;
|
||||
case 5:
|
||||
if (action == MouseAction.ButtonUp)
|
||||
return;
|
||||
wheelDelta = 1;
|
||||
action = MouseAction.Wheel;
|
||||
break;
|
||||
default:
|
||||
// unknown button
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.d("processMouseEvent ", action, " detail=", detail, " state=", state, " at coords ", x, ", ", y);
|
||||
if (action == MouseAction.ButtonDown) {
|
||||
pbuttonDetails.down(x, y, cast(ushort)flags);
|
||||
} else if (action == MouseAction.ButtonUp) {
|
||||
pbuttonDetails.up(x, y, cast(ushort)flags);
|
||||
}
|
||||
MouseEvent event = new MouseEvent(action, button, cast(ushort)flags, x, y, wheelDelta);
|
||||
event.lbutton = _lbutton;
|
||||
event.rbutton = _rbutton;
|
||||
event.mbutton = _mbutton;
|
||||
bool res = dispatchMouseEvent(event);
|
||||
if (res) {
|
||||
Log.d("Calling update() after mouse event");
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private __gshared xcb_connection_t * _xcbconnection;
|
||||
|
@ -342,16 +424,37 @@ version(linux) {
|
|||
case XCB_BUTTON_PRESS: {
|
||||
xcb_button_press_event_t *bp = cast(xcb_button_press_event_t *)e;
|
||||
Log.d("XCB_BUTTON_PRESS");
|
||||
XCBWindow window = getWindow(bp.event);
|
||||
if (window !is null) {
|
||||
//
|
||||
window.processMouseEvent(MouseAction.ButtonDown, bp.detail, bp.state, bp.event_x, bp.event_y);
|
||||
} else {
|
||||
Log.w("Received message for unknown window", bp.event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_RELEASE: {
|
||||
Log.d("XCB_BUTTON_RELEASE");
|
||||
xcb_button_release_event_t *br = cast(xcb_button_release_event_t *)e;
|
||||
XCBWindow window = getWindow(br.event);
|
||||
if (window !is null) {
|
||||
//
|
||||
window.processMouseEvent(MouseAction.ButtonUp, br.detail, br.state, br.event_x, br.event_y);
|
||||
} else {
|
||||
Log.w("Received message for unknown window", br.event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_MOTION_NOTIFY: {
|
||||
xcb_motion_notify_event_t *motion = cast(xcb_motion_notify_event_t *)e;
|
||||
Log.d("XCB_MOTION_NOTIFY ", motion.event, " at coords ", motion.event_x, ", ", motion.event_y);
|
||||
XCBWindow window = getWindow(motion.event);
|
||||
if (window !is null) {
|
||||
//
|
||||
window.processMouseEvent(MouseAction.Move, 0, motion.state, motion.event_x, motion.event_y);
|
||||
} else {
|
||||
Log.w("Received message for unknown window", motion.event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_ENTER_NOTIFY: {
|
||||
|
|
|
@ -415,7 +415,7 @@ class Style {
|
|||
const(Style) forState(uint state) const {
|
||||
if (state == 0)
|
||||
return this;
|
||||
Log.d("forState ", state, " styleId=", _id, " substates=", _substates.length);
|
||||
//Log.d("forState ", state, " styleId=", _id, " substates=", _substates.length);
|
||||
if (id is null && parentStyle !is null && _substates.length == 0)
|
||||
return parentStyle.forState(state);
|
||||
foreach(item; _substates) {
|
||||
|
|
Loading…
Reference in New Issue