mirror of https://github.com/buggins/dlangui.git
fix xcb build; update button resources
This commit is contained in:
parent
27d2f64735
commit
67b4534b70
|
@ -161,11 +161,22 @@
|
||||||
<Compile Include="3rdparty\X11\xcb\xvmc.d" />
|
<Compile Include="3rdparty\X11\xcb\xvmc.d" />
|
||||||
<Compile Include="3rdparty\X11\keysymdef.d" />
|
<Compile Include="3rdparty\X11\keysymdef.d" />
|
||||||
<Compile Include="3rdparty\X11\xcb\image.d" />
|
<Compile Include="3rdparty\X11\xcb\image.d" />
|
||||||
|
<Compile Include="src\dlangui\core\events.d" />
|
||||||
|
<Compile Include="..\DerelictFI\source\derelict\freeimage\freeimage.d">
|
||||||
|
<Link>3rdparty\DerelictFI\freeimage.d</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\DerelictFI\source\derelict\freeimage\functions.d">
|
||||||
|
<Link>3rdparty\DerelictFI\functions.d</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\DerelictFI\source\derelict\freeimage\types.d">
|
||||||
|
<Link>3rdparty\DerelictFI\types.d</Link>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="src\dlangui\platforms\x11\" />
|
<Folder Include="src\dlangui\platforms\x11\" />
|
||||||
<Folder Include="3rdparty\DerelictUtil\" />
|
<Folder Include="3rdparty\DerelictUtil\" />
|
||||||
<Folder Include="3rdparty\DerelictGL3\" />
|
<Folder Include="3rdparty\DerelictGL3\" />
|
||||||
<Folder Include="3rdparty\DerelictFT\" />
|
<Folder Include="3rdparty\DerelictFT\" />
|
||||||
|
<Folder Include="3rdparty\DerelictFI\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -2,419 +2,430 @@ module src.dlangui.platforms.x11.x11app;
|
||||||
|
|
||||||
version(linux) {
|
version(linux) {
|
||||||
|
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.c.linux.X11.xcb.xcb;
|
import std.c.linux.X11.xcb.xcb;
|
||||||
import std.c.linux.X11.xcb.shm;
|
import std.c.linux.X11.xcb.shm;
|
||||||
import std.c.linux.X11.xcb.xproto;
|
import std.c.linux.X11.xcb.xproto;
|
||||||
import std.c.linux.X11.xcb.image;
|
import std.c.linux.X11.xcb.image;
|
||||||
import std.c.linux.X11.keysymdef;
|
import std.c.linux.X11.keysymdef;
|
||||||
import std.c.linux.linux;
|
import std.c.linux.linux;
|
||||||
import std.c.stdlib;
|
import std.c.stdlib;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
|
|
||||||
import dlangui.core.logger;
|
import dlangui.core.logger;
|
||||||
import dlangui.graphics.drawbuf;
|
import dlangui.graphics.drawbuf;
|
||||||
import dlangui.graphics.fonts;
|
import dlangui.graphics.fonts;
|
||||||
import dlangui.graphics.ftfonts;
|
import dlangui.graphics.ftfonts;
|
||||||
import dlangui.platforms.common.platform;
|
import dlangui.platforms.common.platform;
|
||||||
|
|
||||||
class XCBWindow : Window {
|
class XCBWindow : Window {
|
||||||
xcb_window_t _w;
|
xcb_window_t _w;
|
||||||
xcb_gcontext_t _g;
|
xcb_gcontext_t _g;
|
||||||
xcb_image_t * _image;
|
xcb_image_t * _image;
|
||||||
xcb_shm_segment_info_t shminfo;
|
xcb_shm_segment_info_t shminfo;
|
||||||
@property xcb_window_t windowId() { return _w; }
|
@property xcb_window_t windowId() { return _w; }
|
||||||
this(string caption, Window parent) {
|
this(string caption, Window parent) {
|
||||||
_caption = caption;
|
_caption = caption;
|
||||||
Log.d("Creating XCB window");
|
Log.d("Creating XCB window");
|
||||||
create();
|
create();
|
||||||
}
|
|
||||||
~this() {
|
|
||||||
Log.d("Destroying window");
|
|
||||||
}
|
|
||||||
bool create() {
|
|
||||||
uint mask;
|
|
||||||
uint values[2];
|
|
||||||
|
|
||||||
/* create black graphics context */
|
|
||||||
_g = xcb_generate_id(_xcbconnection);
|
|
||||||
_w = _xcbscreen.root;
|
|
||||||
mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
|
|
||||||
values[0] = _xcbscreen.black_pixel;
|
|
||||||
values[1] = 0;
|
|
||||||
xcb_create_gc(_xcbconnection, _g, _w, mask, &values[0]);
|
|
||||||
|
|
||||||
/* create window */
|
|
||||||
_w = xcb_generate_id(_xcbconnection);
|
|
||||||
|
|
||||||
Log.d("window=", _w, " gc=", _g);
|
|
||||||
|
|
||||||
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
|
||||||
values[0] = _xcbscreen.white_pixel;
|
|
||||||
values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
|
|
||||||
| XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_MOTION
|
|
||||||
| XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW
|
|
||||||
| XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE
|
|
||||||
| XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_VISIBILITY_CHANGE;
|
|
||||||
xcb_create_window(_xcbconnection, _xcbscreen.root_depth, _w, _xcbscreen.root,
|
|
||||||
50, 50, 500, 400, 1,
|
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, _xcbscreen.root_visual,
|
|
||||||
mask, &values[0]);
|
|
||||||
xcb_flush(_xcbconnection);
|
|
||||||
windowCaption = _caption;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createImage() {
|
|
||||||
Log.i("CRXCBScreen::createImage ", _dx, "x", _dy);
|
|
||||||
if (_image)
|
|
||||||
xcb_image_destroy(_image);
|
|
||||||
_image = null;
|
|
||||||
xcb_shm_query_version_reply_t * rep_shm;
|
|
||||||
rep_shm = xcb_shm_query_version_reply (_xcbconnection,
|
|
||||||
xcb_shm_query_version(_xcbconnection),
|
|
||||||
null);
|
|
||||||
if(rep_shm) {
|
|
||||||
xcb_image_format_t format;
|
|
||||||
int shmctl_status;
|
|
||||||
|
|
||||||
if (rep_shm.shared_pixmaps &&
|
|
||||||
(rep_shm.major_version > 1 || rep_shm.minor_version > 0))
|
|
||||||
format = cast(xcb_image_format_t)rep_shm.pixmap_format;
|
|
||||||
else
|
|
||||||
format = XCB_IMAGE_FORMAT_Z_PIXMAP;
|
|
||||||
|
|
||||||
_image = xcb_image_create_native (_xcbconnection, cast(short)_dx, cast(short)_dy,
|
|
||||||
format, _xcbscreendepth, null, ~0, null);
|
|
||||||
//format, depth, NULL, ~0, NULL);
|
|
||||||
//format, depth, NULL, ~0, NULL);
|
|
||||||
assert(_image);
|
|
||||||
|
|
||||||
shminfo.shmid = shmget (IPC_PRIVATE,
|
|
||||||
_image.stride*_image.height,
|
|
||||||
IPC_CREAT | octal!777);
|
|
||||||
assert(shminfo.shmid != cast(uint)-1);
|
|
||||||
shminfo.shmaddr = cast(ubyte*)shmat (shminfo.shmid, null, 0);
|
|
||||||
assert(shminfo.shmaddr);
|
|
||||||
_image.data = shminfo.shmaddr;
|
|
||||||
Log.d("Created image depth=", _image.depth, " bpp=", _image.bpp, " stride=", _image.stride );
|
|
||||||
|
|
||||||
shminfo.shmseg = xcb_generate_id (_xcbconnection);
|
|
||||||
xcb_shm_attach (_xcbconnection, shminfo.shmseg,
|
|
||||||
shminfo.shmid, 0);
|
|
||||||
shmctl_status = shmctl(shminfo.shmid, IPC_RMID, null);
|
|
||||||
assert(shmctl_status != -1);
|
|
||||||
free(rep_shm);
|
|
||||||
} else {
|
|
||||||
Log.e("Can't get shms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(ColorDrawBuf buf) {
|
|
||||||
int i;
|
|
||||||
i = xcb_image_shm_get(_xcbconnection, _w,
|
|
||||||
_image, shminfo,
|
|
||||||
0, 0,
|
|
||||||
XCB_ALL_PLANES);
|
|
||||||
if (!i) {
|
|
||||||
Log.e("cannot get shm image");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Rect rc;
|
|
||||||
rc.right = buf.width;
|
|
||||||
rc.bottom = buf.height;
|
|
||||||
switch ( _image.bpp ) {
|
|
||||||
case 32:
|
|
||||||
{
|
|
||||||
for (int y = rc.top; y<rc.bottom; y++) {
|
|
||||||
uint * src = buf.scanLine(y);
|
|
||||||
uint * dst = cast(uint *)(_image.data + _image.stride * y);
|
|
||||||
for ( int x = 0; x < rc.right; x++ ) {
|
|
||||||
uint data = src[x];
|
|
||||||
dst[x] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.d("image bit depth not supported: ", _image.bpp);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
xcb_image_shm_put(_xcbconnection, _w, _g,
|
~this() {
|
||||||
_image, shminfo,
|
Log.d("Destroying window");
|
||||||
cast(short)rc.left, cast(short)rc.top, cast(short)rc.left, cast(short)rc.top, cast(ushort)rc.width(), cast(ushort)rc.height(), 0);
|
|
||||||
xcb_flush(_xcbconnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
override void show() {
|
|
||||||
Log.d("XCBWindow.show()");
|
|
||||||
/* map (show) the window */
|
|
||||||
xcb_map_window(_xcbconnection, _w);
|
|
||||||
xcb_flush(_xcbconnection);
|
|
||||||
}
|
|
||||||
string _caption;
|
|
||||||
override @property string windowCaption() {
|
|
||||||
return _caption;
|
|
||||||
}
|
|
||||||
override @property void windowCaption(string caption) {
|
|
||||||
_caption = caption;
|
|
||||||
const char * title = _caption.toStringz;
|
|
||||||
xcb_change_property (_xcbconnection,
|
|
||||||
XCB_PROP_MODE_REPLACE,
|
|
||||||
_w,
|
|
||||||
XCB_ATOM_WM_NAME,
|
|
||||||
XCB_ATOM_STRING,
|
|
||||||
8,
|
|
||||||
cast(uint)_caption.length,
|
|
||||||
cast(void*)title);
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorDrawBuf _drawbuf;
|
|
||||||
void processExpose(xcb_expose_event_t * event) {
|
|
||||||
if (!_drawbuf)
|
|
||||||
_drawbuf = new ColorDrawBuf(_dx, _dy);
|
|
||||||
_drawbuf.resize(_dx, _dy);
|
|
||||||
Log.d("calling createImage");
|
|
||||||
createImage();
|
|
||||||
Log.d("done createImage");
|
|
||||||
onDraw(_drawbuf);
|
|
||||||
draw(_drawbuf);
|
|
||||||
/*
|
|
||||||
xcb_rectangle_t r = { 20, 20, 60, 60 };
|
|
||||||
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
|
|
||||||
r = xcb_rectangle_t(cast(short)(_dx - 20 - 60), cast(short)(_dy - 20 - 60), 60, 60);
|
|
||||||
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
|
|
||||||
*/
|
|
||||||
xcb_flush(_xcbconnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private __gshared xcb_connection_t * _xcbconnection;
|
|
||||||
private __gshared xcb_screen_t * _xcbscreen;
|
|
||||||
private __gshared ubyte _xcbscreendepth;
|
|
||||||
|
|
||||||
class XCBPlatform : Platform {
|
|
||||||
this() {
|
|
||||||
}
|
|
||||||
~this() {
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
void disconnect() {
|
|
||||||
if (_xcbconnection) {
|
|
||||||
/* close connection to server */
|
|
||||||
xcb_disconnect(_xcbconnection);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
bool connect() {
|
|
||||||
Log.d("Opening connection");
|
|
||||||
/* open connection with the server */
|
|
||||||
_xcbconnection = xcb_connect(null,null);
|
|
||||||
if (xcb_connection_has_error(_xcbconnection)) {
|
|
||||||
Log.e("Cannot open display");
|
|
||||||
_xcbconnection = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//XSetEventQueueOwner(display, XCBOwnsEventQueue);
|
|
||||||
Log.d("Getting first screen");
|
|
||||||
/* get the first screen */
|
|
||||||
_xcbscreen = xcb_setup_roots_iterator( xcb_get_setup(_xcbconnection) ).data;
|
|
||||||
_xcbscreendepth = xcb_aux_get_depth(_xcbconnection, _xcbscreen);
|
|
||||||
|
|
||||||
return true;
|
/// request window redraw
|
||||||
}
|
override void invalidate() {
|
||||||
XCBWindow getWindow(xcb_window_t w) {
|
redraw();
|
||||||
if (w in _windowMap)
|
}
|
||||||
return _windowMap[w];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
override Window createWindow(string windowCaption, Window parent) {
|
|
||||||
XCBWindow res = new XCBWindow(windowCaption, parent);
|
|
||||||
_windowMap[res.windowId] = res;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
override int enterMessageLoop() {
|
|
||||||
Log.i("entering message loop");
|
|
||||||
int done = 0;
|
|
||||||
xcb_generic_event_t *e;
|
|
||||||
/* event loop */
|
|
||||||
do {
|
|
||||||
e = xcb_wait_for_event(_xcbconnection);
|
|
||||||
if (e is null) {
|
|
||||||
Log.w("NULL event received. Exiting message loop");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (e.response_type & ~0x80) {
|
|
||||||
case XCB_CREATE_NOTIFY: {
|
|
||||||
xcb_create_notify_event_t *event = cast(xcb_create_notify_event_t *)e;
|
|
||||||
Log.i("XCB_CREATE_NOTIFY");
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_DESTROY_NOTIFY: {
|
|
||||||
xcb_destroy_notify_event_t *event = cast(xcb_destroy_notify_event_t *)e;
|
|
||||||
Log.i("XCB_DESTROY_NOTIFY");
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_MAP_NOTIFY: {
|
|
||||||
xcb_map_notify_event_t *event = cast(xcb_map_notify_event_t *)e;
|
|
||||||
Log.i("XCB_MAP_NOTIFY");
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_UNMAP_NOTIFY: {
|
|
||||||
xcb_unmap_notify_event_t *event = cast(xcb_unmap_notify_event_t *)e;
|
|
||||||
Log.i("XCB_UNMAP_NOTIFY");
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_VISIBILITY_NOTIFY: {
|
|
||||||
xcb_visibility_notify_event_t *event = cast(xcb_visibility_notify_event_t *)e;
|
|
||||||
Log.i("XCB_VISIBILITY_NOTIFY ", event.state);
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_REPARENT_NOTIFY: {
|
|
||||||
xcb_reparent_notify_event_t *event = cast(xcb_reparent_notify_event_t *)e;
|
|
||||||
Log.i("XCB_REPARENT_NOTIFY");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_CONFIGURE_NOTIFY: {
|
|
||||||
xcb_configure_notify_event_t *event = cast(xcb_configure_notify_event_t *)e;
|
|
||||||
Log.i("XCB_CONFIGURE_NOTIFY ", event.width, "x", event.height);
|
|
||||||
XCBWindow window = getWindow(event.window);
|
|
||||||
if (window !is null) {
|
|
||||||
//
|
|
||||||
window.onResize(event.width, event.height);
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", event.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_EXPOSE: { /* draw or redraw the window */
|
|
||||||
xcb_expose_event_t *expose = cast(xcb_expose_event_t *)e;
|
|
||||||
Log.i("XCB_EXPOSE");
|
|
||||||
XCBWindow window = getWindow(expose.window);
|
|
||||||
if (window !is null) {
|
|
||||||
window.processExpose(expose);
|
|
||||||
} else {
|
|
||||||
Log.w("Received message for unknown window", expose.window);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_BUTTON_PRESS: {
|
|
||||||
xcb_button_press_event_t *bp = cast(xcb_button_press_event_t *)e;
|
|
||||||
Log.d("XCB_BUTTON_PRESS");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_BUTTON_RELEASE: {
|
|
||||||
Log.d("XCB_BUTTON_RELEASE");
|
|
||||||
xcb_button_release_event_t *br = cast(xcb_button_release_event_t *)e;
|
|
||||||
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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_ENTER_NOTIFY: {
|
|
||||||
xcb_enter_notify_event_t *enter = cast(xcb_enter_notify_event_t *)e;
|
|
||||||
Log.d("XCB_ENTER_NOTIFY ", enter.event, " at coords ", enter.event_x, ", ", enter.event_y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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);
|
bool create() {
|
||||||
|
uint mask;
|
||||||
|
uint values[2];
|
||||||
|
|
||||||
|
/* create black graphics context */
|
||||||
|
_g = xcb_generate_id(_xcbconnection);
|
||||||
|
_w = _xcbscreen.root;
|
||||||
|
mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
|
||||||
|
values[0] = _xcbscreen.black_pixel;
|
||||||
|
values[1] = 0;
|
||||||
|
xcb_create_gc(_xcbconnection, _g, _w, mask, &values[0]);
|
||||||
|
|
||||||
|
/* create window */
|
||||||
|
_w = xcb_generate_id(_xcbconnection);
|
||||||
|
|
||||||
|
Log.d("window=", _w, " gc=", _g);
|
||||||
|
|
||||||
|
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||||
|
values[0] = _xcbscreen.white_pixel;
|
||||||
|
values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
|
||||||
|
| XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_MOTION
|
||||||
|
| XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW
|
||||||
|
| XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE
|
||||||
|
| XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_VISIBILITY_CHANGE;
|
||||||
|
xcb_create_window(_xcbconnection, _xcbscreen.root_depth, _w, _xcbscreen.root,
|
||||||
|
50, 50, 500, 400, 1,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, _xcbscreen.root_visual,
|
||||||
|
mask, &values[0]);
|
||||||
|
xcb_flush(_xcbconnection);
|
||||||
|
windowCaption = _caption;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createImage() {
|
||||||
|
Log.i("CRXCBScreen::createImage ", _dx, "x", _dy);
|
||||||
|
if (_image)
|
||||||
|
xcb_image_destroy(_image);
|
||||||
|
_image = null;
|
||||||
|
xcb_shm_query_version_reply_t * rep_shm;
|
||||||
|
rep_shm = xcb_shm_query_version_reply (_xcbconnection,
|
||||||
|
xcb_shm_query_version(_xcbconnection),
|
||||||
|
null);
|
||||||
|
if(rep_shm) {
|
||||||
|
xcb_image_format_t format;
|
||||||
|
int shmctl_status;
|
||||||
|
|
||||||
|
if (rep_shm.shared_pixmaps &&
|
||||||
|
(rep_shm.major_version > 1 || rep_shm.minor_version > 0))
|
||||||
|
format = cast(xcb_image_format_t)rep_shm.pixmap_format;
|
||||||
|
else
|
||||||
|
format = XCB_IMAGE_FORMAT_Z_PIXMAP;
|
||||||
|
|
||||||
|
_image = xcb_image_create_native (_xcbconnection, cast(short)_dx, cast(short)_dy,
|
||||||
|
format, _xcbscreendepth, null, ~0, null);
|
||||||
|
//format, depth, NULL, ~0, NULL);
|
||||||
|
//format, depth, NULL, ~0, NULL);
|
||||||
|
assert(_image);
|
||||||
|
|
||||||
|
shminfo.shmid = shmget (IPC_PRIVATE,
|
||||||
|
_image.stride*_image.height,
|
||||||
|
IPC_CREAT | octal!777);
|
||||||
|
assert(shminfo.shmid != cast(uint)-1);
|
||||||
|
shminfo.shmaddr = cast(ubyte*)shmat (shminfo.shmid, null, 0);
|
||||||
|
assert(shminfo.shmaddr);
|
||||||
|
_image.data = shminfo.shmaddr;
|
||||||
|
Log.d("Created image depth=", _image.depth, " bpp=", _image.bpp, " stride=", _image.stride );
|
||||||
|
|
||||||
|
shminfo.shmseg = xcb_generate_id (_xcbconnection);
|
||||||
|
xcb_shm_attach (_xcbconnection, shminfo.shmseg,
|
||||||
|
shminfo.shmid, 0);
|
||||||
|
shmctl_status = shmctl(shminfo.shmid, IPC_RMID, null);
|
||||||
|
assert(shmctl_status != -1);
|
||||||
|
free(rep_shm);
|
||||||
|
} else {
|
||||||
|
Log.e("Can't get shms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(ColorDrawBuf buf) {
|
||||||
|
int i;
|
||||||
|
i = xcb_image_shm_get(_xcbconnection, _w,
|
||||||
|
_image, shminfo,
|
||||||
|
0, 0,
|
||||||
|
XCB_ALL_PLANES);
|
||||||
|
if (!i) {
|
||||||
|
Log.e("cannot get shm image");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Rect rc;
|
||||||
|
rc.right = buf.width;
|
||||||
|
rc.bottom = buf.height;
|
||||||
|
switch ( _image.bpp ) {
|
||||||
|
case 32:
|
||||||
|
{
|
||||||
|
for (int y = rc.top; y<rc.bottom; y++) {
|
||||||
|
uint * src = buf.scanLine(y);
|
||||||
|
uint * dst = cast(uint *)(_image.data + _image.stride * y);
|
||||||
|
for ( int x = 0; x < rc.right; x++ ) {
|
||||||
|
uint data = src[x];
|
||||||
|
dst[x] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case XCB_KEY_PRESS: {
|
|
||||||
xcb_key_press_event_t *kp = cast(xcb_key_press_event_t *)e;
|
|
||||||
//print_modifiers(kp.state);
|
|
||||||
Log.d("XCB_KEY_PRESS ", kp.event, " key=", kp.detail);
|
|
||||||
if (kp.detail == XK_space) // exist by space
|
|
||||||
done = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XCB_KEY_RELEASE: {
|
|
||||||
xcb_key_release_event_t *kr = cast(xcb_key_release_event_t *)e;
|
|
||||||
//print_modifiers(kr.state);
|
|
||||||
Log.d("XCB_KEY_RELEASE ", kr.event, " key=", kr.detail);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
Log.v("unknown event: ", e.response_type & ~0x80);
|
Log.d("image bit depth not supported: ", _image.bpp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(e);
|
xcb_image_shm_put(_xcbconnection, _w, _g,
|
||||||
} while(!done);
|
_image, shminfo,
|
||||||
Log.i("exiting message loop");
|
cast(short)rc.left, cast(short)rc.top, cast(short)rc.left, cast(short)rc.top, cast(ushort)rc.width(), cast(ushort)rc.height(), 0);
|
||||||
return 0;
|
xcb_flush(_xcbconnection);
|
||||||
}
|
|
||||||
XCBWindow[xcb_window_t] _windowMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// entry point
|
|
||||||
extern(C) int UIAppMain(string[] args);
|
|
||||||
|
|
||||||
int main(string[] args)
|
|
||||||
{
|
|
||||||
|
|
||||||
setStderrLogger();
|
|
||||||
setLogLevel(LogLevel.Trace);
|
|
||||||
|
|
||||||
FreeTypeFontManager ft = new FreeTypeFontManager();
|
|
||||||
ft.registerFont("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FontFamily.SansSerif, "DejaVu", false, FontWeight.Normal);
|
|
||||||
FontManager.instance = ft;
|
|
||||||
|
|
||||||
XCBPlatform xcb = new XCBPlatform();
|
|
||||||
if (!xcb.connect()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
Platform.setInstance(xcb);
|
|
||||||
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
static if (true) {
|
|
||||||
res = UIAppMain(args);
|
|
||||||
} else {
|
|
||||||
Window window = xcb.createWindow("Window Caption", null);
|
|
||||||
window.show();
|
|
||||||
|
|
||||||
res = xcb.enterMessageLoop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform.setInstance(null);
|
override void show() {
|
||||||
destroy(xcb);
|
Log.d("XCBWindow.show()");
|
||||||
|
/* map (show) the window */
|
||||||
|
xcb_map_window(_xcbconnection, _w);
|
||||||
|
xcb_flush(_xcbconnection);
|
||||||
|
}
|
||||||
|
string _caption;
|
||||||
|
override @property string windowCaption() {
|
||||||
|
return _caption;
|
||||||
|
}
|
||||||
|
override @property void windowCaption(string caption) {
|
||||||
|
_caption = caption;
|
||||||
|
const char * title = _caption.toStringz;
|
||||||
|
xcb_change_property (_xcbconnection,
|
||||||
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
_w,
|
||||||
|
XCB_ATOM_WM_NAME,
|
||||||
|
XCB_ATOM_STRING,
|
||||||
|
8,
|
||||||
|
cast(uint)_caption.length,
|
||||||
|
cast(void*)title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void redraw() {
|
||||||
|
if (!_drawbuf)
|
||||||
|
_drawbuf = new ColorDrawBuf(_dx, _dy);
|
||||||
|
_drawbuf.resize(_dx, _dy);
|
||||||
|
_drawbuf.fill(_backgroundColor);
|
||||||
|
Log.d("calling createImage");
|
||||||
|
createImage();
|
||||||
|
Log.d("done createImage");
|
||||||
|
onDraw(_drawbuf);
|
||||||
|
draw(_drawbuf);
|
||||||
|
/*
|
||||||
|
xcb_rectangle_t r = { 20, 20, 60, 60 };
|
||||||
|
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
|
||||||
|
r = xcb_rectangle_t(cast(short)(_dx - 20 - 60), cast(short)(_dy - 20 - 60), 60, 60);
|
||||||
|
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
|
||||||
|
*/
|
||||||
|
xcb_flush(_xcbconnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorDrawBuf _drawbuf;
|
||||||
|
void processExpose(xcb_expose_event_t * event) {
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private __gshared xcb_connection_t * _xcbconnection;
|
||||||
|
private __gshared xcb_screen_t * _xcbscreen;
|
||||||
|
private __gshared ubyte _xcbscreendepth;
|
||||||
|
|
||||||
|
class XCBPlatform : Platform {
|
||||||
|
this() {
|
||||||
|
}
|
||||||
|
~this() {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
void disconnect() {
|
||||||
|
if (_xcbconnection) {
|
||||||
|
/* close connection to server */
|
||||||
|
xcb_disconnect(_xcbconnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool connect() {
|
||||||
|
Log.d("Opening connection");
|
||||||
|
/* open connection with the server */
|
||||||
|
_xcbconnection = xcb_connect(null,null);
|
||||||
|
if (xcb_connection_has_error(_xcbconnection)) {
|
||||||
|
Log.e("Cannot open display");
|
||||||
|
_xcbconnection = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//XSetEventQueueOwner(display, XCBOwnsEventQueue);
|
||||||
|
Log.d("Getting first screen");
|
||||||
|
/* get the first screen */
|
||||||
|
_xcbscreen = xcb_setup_roots_iterator( xcb_get_setup(_xcbconnection) ).data;
|
||||||
|
_xcbscreendepth = xcb_aux_get_depth(_xcbconnection, _xcbscreen);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
XCBWindow getWindow(xcb_window_t w) {
|
||||||
|
if (w in _windowMap)
|
||||||
|
return _windowMap[w];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
override Window createWindow(string windowCaption, Window parent) {
|
||||||
|
XCBWindow res = new XCBWindow(windowCaption, parent);
|
||||||
|
_windowMap[res.windowId] = res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
override int enterMessageLoop() {
|
||||||
|
Log.i("entering message loop");
|
||||||
|
int done = 0;
|
||||||
|
xcb_generic_event_t *e;
|
||||||
|
/* event loop */
|
||||||
|
do {
|
||||||
|
e = xcb_wait_for_event(_xcbconnection);
|
||||||
|
if (e is null) {
|
||||||
|
Log.w("NULL event received. Exiting message loop");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (e.response_type & ~0x80) {
|
||||||
|
case XCB_CREATE_NOTIFY: {
|
||||||
|
xcb_create_notify_event_t *event = cast(xcb_create_notify_event_t *)e;
|
||||||
|
Log.i("XCB_CREATE_NOTIFY");
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_DESTROY_NOTIFY: {
|
||||||
|
xcb_destroy_notify_event_t *event = cast(xcb_destroy_notify_event_t *)e;
|
||||||
|
Log.i("XCB_DESTROY_NOTIFY");
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_MAP_NOTIFY: {
|
||||||
|
xcb_map_notify_event_t *event = cast(xcb_map_notify_event_t *)e;
|
||||||
|
Log.i("XCB_MAP_NOTIFY");
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_UNMAP_NOTIFY: {
|
||||||
|
xcb_unmap_notify_event_t *event = cast(xcb_unmap_notify_event_t *)e;
|
||||||
|
Log.i("XCB_UNMAP_NOTIFY");
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_VISIBILITY_NOTIFY: {
|
||||||
|
xcb_visibility_notify_event_t *event = cast(xcb_visibility_notify_event_t *)e;
|
||||||
|
Log.i("XCB_VISIBILITY_NOTIFY ", event.state);
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_REPARENT_NOTIFY: {
|
||||||
|
xcb_reparent_notify_event_t *event = cast(xcb_reparent_notify_event_t *)e;
|
||||||
|
Log.i("XCB_REPARENT_NOTIFY");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_CONFIGURE_NOTIFY: {
|
||||||
|
xcb_configure_notify_event_t *event = cast(xcb_configure_notify_event_t *)e;
|
||||||
|
Log.i("XCB_CONFIGURE_NOTIFY ", event.width, "x", event.height);
|
||||||
|
XCBWindow window = getWindow(event.window);
|
||||||
|
if (window !is null) {
|
||||||
|
//
|
||||||
|
window.onResize(event.width, event.height);
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", event.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_EXPOSE: { /* draw or redraw the window */
|
||||||
|
xcb_expose_event_t *expose = cast(xcb_expose_event_t *)e;
|
||||||
|
Log.i("XCB_EXPOSE");
|
||||||
|
XCBWindow window = getWindow(expose.window);
|
||||||
|
if (window !is null) {
|
||||||
|
window.processExpose(expose);
|
||||||
|
} else {
|
||||||
|
Log.w("Received message for unknown window", expose.window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_PRESS: {
|
||||||
|
xcb_button_press_event_t *bp = cast(xcb_button_press_event_t *)e;
|
||||||
|
Log.d("XCB_BUTTON_PRESS");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_BUTTON_RELEASE: {
|
||||||
|
Log.d("XCB_BUTTON_RELEASE");
|
||||||
|
xcb_button_release_event_t *br = cast(xcb_button_release_event_t *)e;
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_ENTER_NOTIFY: {
|
||||||
|
xcb_enter_notify_event_t *enter = cast(xcb_enter_notify_event_t *)e;
|
||||||
|
Log.d("XCB_ENTER_NOTIFY ", enter.event, " at coords ", enter.event_x, ", ", enter.event_y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_KEY_PRESS: {
|
||||||
|
xcb_key_press_event_t *kp = cast(xcb_key_press_event_t *)e;
|
||||||
|
//print_modifiers(kp.state);
|
||||||
|
Log.d("XCB_KEY_PRESS ", kp.event, " key=", kp.detail);
|
||||||
|
if (kp.detail == XK_space) // exist by space
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_KEY_RELEASE: {
|
||||||
|
xcb_key_release_event_t *kr = cast(xcb_key_release_event_t *)e;
|
||||||
|
//print_modifiers(kr.state);
|
||||||
|
Log.d("XCB_KEY_RELEASE ", kr.event, " key=", kr.detail);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Log.v("unknown event: ", e.response_type & ~0x80);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(e);
|
||||||
|
} while(!done);
|
||||||
|
Log.i("exiting message loop");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
XCBWindow[xcb_window_t] _windowMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry point
|
||||||
|
extern(C) int UIAppMain(string[] args);
|
||||||
|
|
||||||
|
int main(string[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
setStderrLogger();
|
||||||
|
setLogLevel(LogLevel.Trace);
|
||||||
|
|
||||||
|
FreeTypeFontManager ft = new FreeTypeFontManager();
|
||||||
|
ft.registerFont("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FontFamily.SansSerif, "DejaVu", false, FontWeight.Normal);
|
||||||
|
FontManager.instance = ft;
|
||||||
|
|
||||||
|
XCBPlatform xcb = new XCBPlatform();
|
||||||
|
if (!xcb.connect()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Platform.setInstance(xcb);
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
static if (true) {
|
||||||
|
res = UIAppMain(args);
|
||||||
|
} else {
|
||||||
|
Window window = xcb.createWindow("Window Caption", null);
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
res = xcb.enterMessageLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.setInstance(null);
|
||||||
|
destroy(xcb);
|
||||||
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,8 +502,10 @@ private __gshared Theme _currentTheme;
|
||||||
|
|
||||||
static this() {
|
static this() {
|
||||||
_currentTheme = new Theme("default");
|
_currentTheme = new Theme("default");
|
||||||
Style button = _currentTheme.createSubstyle("BUTTON").backgroundImageId("btn_default_normal").alignment(Align.Center);
|
Style button = _currentTheme.createSubstyle("BUTTON").backgroundImageId("btn_default_small_normal").alignment(Align.Center);
|
||||||
Style text = _currentTheme.createSubstyle("TEXT").margins(Rect(3,3,3,3)).padding(Rect(3,3,3,3));
|
Style text = _currentTheme.createSubstyle("TEXT").margins(Rect(3,3,3,3)).padding(Rect(3,3,3,3));
|
||||||
button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_pressed");
|
button.createState(State.Disabled | State.Focused, State.Disabled | State.Focused).backgroundImageId("btn_default_small_normal_disable_focused");
|
||||||
button.createState(State.Focused, State.Focused).backgroundImageId("btn_default_selected");
|
button.createState(State.Disabled, State.Disabled).backgroundImageId("btn_default_small_normal_disable");
|
||||||
|
button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_small_pressed");
|
||||||
|
button.createState(State.Focused, State.Focused).backgroundImageId("btn_default_small_selected");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue