diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index 1c67d687..7b3c0e7e 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -294,6 +294,7 @@ + diff --git a/src/dlangui/all.d b/src/dlangui/all.d index 29d65642..2a0858e7 100644 --- a/src/dlangui/all.d +++ b/src/dlangui/all.d @@ -63,3 +63,4 @@ public import dlangui.widgets.tree; public import dlangui.widgets.combobox; public import dlangui.graphics.fonts; public import dlangui.core.i18n; +public import dlangui.core.files; diff --git a/src/dlangui/core/i18n.d b/src/dlangui/core/i18n.d index c50b22dc..76309ef8 100644 --- a/src/dlangui/core/i18n.d +++ b/src/dlangui/core/i18n.d @@ -58,6 +58,7 @@ module dlangui.core.i18n; import dlangui.core.types; import dlangui.core.logger; +import dlangui.core.files; private import dlangui.core.linestream; private import std.utf; private import std.algorithm; diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index e22cb5ac..96ec7531 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -390,82 +390,3 @@ dchar dcharToUpper(dchar ch) { return ch; } -version (Windows) { - /// path delimiter (\ for windows, / for others) - immutable char PATH_DELIMITER = '\\'; -} else { - /// path delimiter (\ for windows, / for others) - immutable char PATH_DELIMITER = '/'; -} - -/** returns true if char ch is / or \ slash */ -bool isPathDelimiter(char ch) { - return ch == '/' || ch == '\\'; -} - -/** returns current executable path only, including last path delimiter */ -@property string exePath() { - import std.file; - string path = thisExePath(); - int lastSlash = 0; - for (int i = 0; i < path.length; i++) - if (path[i] == PATH_DELIMITER) - lastSlash = i; - return path[0 .. lastSlash + 1]; -} - -/// converts path delimiters to standard for platform inplace in buffer(e.g. / to \ on windows, \ to / on posix), returns buf -char[] convertPathDelimiters(char[] buf) { - foreach(ref ch; buf) { - version (Windows) { - if (ch == '/') - ch = '\\'; - } else { - if (ch == '\\') - ch = '/'; - } - } - return buf; -} - -/** converts path delimiters to standard for platform (e.g. / to \ on windows, \ to / on posix) */ -string convertPathDelimiters(string src) { - char[] buf = src.dup; - return cast(string)convertPathDelimiters(buf); -} - -/** appends file path parts with proper delimiters e.g. appendPath("/home/user", ".myapp", "config") => "/home/user/.myapp/config" */ -string appendPath(string[] pathItems ...) { - char[] buf; - foreach (s; pathItems) { - if (buf.length && !isPathDelimiter(buf[$-1])) - buf ~= PATH_DELIMITER; - buf ~= s; - } - return convertPathDelimiters(buf).dup; -} - -/** appends file path parts with proper delimiters (as well converts delimiters inside path to system) to buffer e.g. appendPath("/home/user", ".myapp", "config") => "/home/user/.myapp/config" */ -char[] appendPath(char[] buf, string[] pathItems ...) { - foreach (s; pathItems) { - if (buf.length && !isPathDelimiter(buf[$-1])) - buf ~= PATH_DELIMITER; - buf ~= s; - } - return convertPathDelimiters(buf); -} - -/** split path into elements, e.g. /home/user/dir1 -> ["home", "user", "dir1"], "c:\dir1\dir2" -> ["c:", "dir1", "dir2"] */ -string[] splitPath(string path) { - string[] res; - int start = 0; - for (int i = 0; i <= path.length; i++) { - char ch = i < path.length ? path[i] : 0; - if (ch == '\\' || ch == '/' || ch == 0) { - if (start < i) - res ~= path[start .. i].dup; - start = i + 1; - } - } - return res; -} diff --git a/src/dlangui/dialogs/filedlg.d b/src/dlangui/dialogs/filedlg.d index 34436adb..88475cef 100644 --- a/src/dlangui/dialogs/filedlg.d +++ b/src/dlangui/dialogs/filedlg.d @@ -26,6 +26,7 @@ module dlangui.dialogs.filedlg; import dlangui.core.events; import dlangui.core.i18n; import dlangui.core.stdaction; +import dlangui.core.files; import dlangui.widgets.controls; import dlangui.widgets.lists; import dlangui.widgets.popup; diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index fe2078dc..a8ea4199 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -28,6 +28,7 @@ import std.file; import dlangui.core.logger; import dlangui.core.events; +import dlangui.core.files; import dlangui.graphics.drawbuf; import dlangui.graphics.fonts; import dlangui.graphics.ftfonts; diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index c62a9946..ea73a720 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -39,6 +39,7 @@ import dlangui.graphics.drawbuf; import dlangui.graphics.images; import dlangui.graphics.fonts; import dlangui.core.logger; +import dlangui.core.files; version (USE_OPENGL) { import dlangui.graphics.glsupport; diff --git a/src/dlangui/platforms/x11/x11app.d b/src/dlangui/platforms/x11/x11app.d index 996f0910..8b597d6d 100644 --- a/src/dlangui/platforms/x11/x11app.d +++ b/src/dlangui/platforms/x11/x11app.d @@ -1,32 +1,55 @@ +// Written in the D programming language. + +/** + +This module contains implementation of Win32 platform support + +Provides XCB platform and window classes. + +Usually you don't need to use this module directly. + +NOTE: Current implementation of XCB backend does not work well. Consider using of SDL2 backend instead. + +Synopsis: + +---- +import dlangui.platforms.x11.x11app; +---- + +Copyright: Vadim Lopatin, 2014 +License: Boost License 1.0 +Authors: Vadim Lopatin, coolreader.org@gmail.com +*/ module src.dlangui.platforms.x11.x11app; -version(USE_XCB) { +version(USE_XCB): - import std.string; - import std.c.linux.X11.xcb.xcb; - import std.c.linux.X11.xcb.shm; - import std.c.linux.X11.xcb.xproto; - import std.c.linux.X11.xcb.image; - import std.c.linux.X11.keysymdef; - import std.c.linux.linux; - import std.c.stdlib; - import std.conv; +import std.string; +import std.c.linux.X11.xcb.xcb; +import std.c.linux.X11.xcb.shm; +import std.c.linux.X11.xcb.xproto; +import std.c.linux.X11.xcb.image; +import std.c.linux.X11.keysymdef; +import std.c.linux.linux; +import std.c.stdlib; +import std.conv; - import dlangui.core.logger; - import dlangui.core.events; - import dlangui.graphics.drawbuf; - import dlangui.graphics.fonts; - import dlangui.graphics.ftfonts; - import dlangui.graphics.resources; - import dlangui.widgets.styles; - import dlangui.platforms.common.platform; +import dlangui.core.logger; +import dlangui.core.events; +import dlangui.core.files; +import dlangui.graphics.drawbuf; +import dlangui.graphics.fonts; +import dlangui.graphics.ftfonts; +import dlangui.graphics.resources; +import dlangui.widgets.styles; +import dlangui.platforms.common.platform; - version (USE_OPENGL) { - import dlangui.graphics.glsupport; - } +version (USE_OPENGL) { + import dlangui.graphics.glsupport; +} - import derelict.opengl3.gl3; - import derelict.opengl3.glx; +import derelict.opengl3.gl3; +import derelict.opengl3.glx; // pragma(lib, "xcb"); // pragma(lib, "xcb-shm"); @@ -35,1139 +58,1137 @@ version(USE_XCB) { // pragma(lib, "X11"); // pragma(lib, "dl"); - extern (System) - xcb_connection_t *XGetXCBConnection(std.c.linux.X11.Xlib.Display *dpy); - enum XEventQueueOwner { XlibOwnsEventQueue = 0, XCBOwnsEventQueue }; - extern (System) - void XSetEventQueueOwner(std.c.linux.X11.Xlib.Display *dpy, XEventQueueOwner owner); +extern (System) +xcb_connection_t *XGetXCBConnection(std.c.linux.X11.Xlib.Display *dpy); +enum XEventQueueOwner { XlibOwnsEventQueue = 0, XCBOwnsEventQueue }; +extern (System) +void XSetEventQueueOwner(std.c.linux.X11.Xlib.Display *dpy, XEventQueueOwner owner); - struct xcb_key_symbols_t {}; - /* enumeration for col parameter? */ - enum xcb_lookup_t { - xcb_lookup_none_t = 1, - xcb_lookup_chars_t = 2, - xcb_lookup_key_sym_t = 3, - xcb_lookup_both_t = 4 - }; +struct xcb_key_symbols_t {}; +/* enumeration for col parameter? */ +enum xcb_lookup_t { + xcb_lookup_none_t = 1, + xcb_lookup_chars_t = 2, + xcb_lookup_key_sym_t = 3, + xcb_lookup_both_t = 4 +}; - extern(C) xcb_key_symbols_t *xcb_key_symbols_alloc (xcb_connection_t *c); +extern(C) xcb_key_symbols_t *xcb_key_symbols_alloc (xcb_connection_t *c); - extern(C) void xcb_key_symbols_free (xcb_key_symbols_t *syms); +extern(C) void xcb_key_symbols_free (xcb_key_symbols_t *syms); - extern(C) xcb_keysym_t xcb_key_symbols_get_keysym (xcb_key_symbols_t *syms, - xcb_keycode_t keycode, - int col); +extern(C) xcb_keysym_t xcb_key_symbols_get_keysym (xcb_key_symbols_t *syms, + xcb_keycode_t keycode, + int col); - extern(C) xcb_keysym_t xcb_key_press_lookup_keysym (xcb_key_symbols_t *syms, - xcb_key_press_event_t *event, - int col); +extern(C) xcb_keysym_t xcb_key_press_lookup_keysym (xcb_key_symbols_t *syms, + xcb_key_press_event_t *event, + int col); - extern(C) xcb_keysym_t xcb_key_release_lookup_keysym (xcb_key_symbols_t *syms, - xcb_key_release_event_t *event, - int col); - class XCBWindow : Window { - xcb_window_t _w; - xcb_gcontext_t _g; - xcb_image_t * _image; - xcb_shm_segment_info_t shminfo; - version(USE_OPENGL) { - /* Create GLX Window */ - private GLXDrawable _drawable; - private GLXWindow _glxwindow; - private GLXContext _context; - private GLXFBConfig _fb_config; - } - private int _visualID = 0; - private xcb_colormap_t _colormap; +extern(C) xcb_keysym_t xcb_key_release_lookup_keysym (xcb_key_symbols_t *syms, + xcb_key_release_event_t *event, + int col); +class XCBWindow : Window { + xcb_window_t _w; + xcb_gcontext_t _g; + xcb_image_t * _image; + xcb_shm_segment_info_t shminfo; + version(USE_OPENGL) { + /* Create GLX Window */ + private GLXDrawable _drawable; + private GLXWindow _glxwindow; + private GLXContext _context; + private GLXFBConfig _fb_config; + } + private int _visualID = 0; + private xcb_colormap_t _colormap; - @property xcb_window_t windowId() { return _w; } - this(string caption, Window parent) { - _caption = caption; - Log.d("Creating XCB window"); - create(); - } - ~this() { - Log.d("Destroying window"); + @property xcb_window_t windowId() { return _w; } + this(string caption, Window parent) { + _caption = caption; + Log.d("Creating XCB window"); + create(); + } + ~this() { + Log.d("Destroying window"); + } + + bool create() { + import std.c.linux.X11.Xlib; + + uint mask; + uint values[3]; + + // disable opengl for testing + _enableOpengl = false; + /* create black graphics context */ + if (true || !_enableOpengl) { + _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]); } + + ubyte depth = _xcbscreen.root_depth; + /* create window */ + _w = xcb_generate_id(_xcbconnection); - bool create() { - import std.c.linux.X11.Xlib; - - uint mask; - uint values[3]; - - // disable opengl for testing - _enableOpengl = false; - /* create black graphics context */ - if (true || !_enableOpengl) { - _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]); - } - - ubyte depth = _xcbscreen.root_depth; - /* create window */ - _w = xcb_generate_id(_xcbconnection); - - Log.d("window=", _w, " gc=", _g); - version (USE_OPENGL) { - if (_enableOpengl) { - int visual_attribs[] = [ - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_DOUBLEBUFFER, 1, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - std.c.linux.X11.Xlib.None]; - - Log.d("Getting framebuffer config"); - int fbcount; - GLXFBConfig *fbc = glXChooseFBConfig(_display, DefaultScreen(_display), visual_attribs.ptr, &fbcount); - if (!fbc) - { - Log.d("Failed to retrieve a framebuffer config"); - //return 1; - } - - Log.d("Getting XVisualInfo"); - _fb_config = fbc[0]; - auto vi = glXGetVisualFromFBConfig(_display, _fb_config); - - //auto vi = glXChooseVisual(_display, std.c.linux.X11.Xlib.DefaultScreen(_display), attributeList.ptr); - _visualID = vi.visualid; - //swa.colormap = std.c.linux.X11.Xlib.XCreateColormap(_display, std.c.linux.X11.Xlib.RootWindow(_display, vi.screen), vi.visual, 0); // AllocNone - - Log.d("Creating color map"); - _colormap = xcb_generate_id(_xcbconnection); - /* Create colormap */ - xcb_create_colormap( - _xcbconnection, - XCB_COLORMAP_ALLOC_NONE, - _colormap, - _xcbscreen.root, - _visualID - ); - depth = cast(ubyte)vi.depth; - } - } - //mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - //values[0] = _xcbscreen.white_pixel; - - int visualId; - uint eventmask = - 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; + Log.d("window=", _w, " gc=", _g); + version (USE_OPENGL) { if (_enableOpengl) { - mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; - values[0] = _xcbscreen.white_pixel; - values[1] = eventmask; - values[2] = _colormap; - //visualId = _xcbscreen.root_visual; - visualId = _visualID; - } else { - mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - values[0] = _xcbscreen.white_pixel; - values[1] = eventmask; - visualId = _xcbscreen.root_visual; + int visual_attribs[] = [ + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, 1, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + std.c.linux.X11.Xlib.None]; + + Log.d("Getting framebuffer config"); + int fbcount; + GLXFBConfig *fbc = glXChooseFBConfig(_display, DefaultScreen(_display), visual_attribs.ptr, &fbcount); + if (!fbc) + { + Log.d("Failed to retrieve a framebuffer config"); + //return 1; + } + + Log.d("Getting XVisualInfo"); + _fb_config = fbc[0]; + auto vi = glXGetVisualFromFBConfig(_display, _fb_config); + + //auto vi = glXChooseVisual(_display, std.c.linux.X11.Xlib.DefaultScreen(_display), attributeList.ptr); + _visualID = vi.visualid; + //swa.colormap = std.c.linux.X11.Xlib.XCreateColormap(_display, std.c.linux.X11.Xlib.RootWindow(_display, vi.screen), vi.visual, 0); // AllocNone + + Log.d("Creating color map"); + _colormap = xcb_generate_id(_xcbconnection); + /* Create colormap */ + xcb_create_colormap( + _xcbconnection, + XCB_COLORMAP_ALLOC_NONE, + _colormap, + _xcbscreen.root, + _visualID + ); + depth = cast(ubyte)vi.depth; } - Log.d("xcb_create_window - window=", _w, " VisualID=", _visualID); - auto res = xcb_create_window(_xcbconnection, - depth, //_xcbscreen.root_depth, - //XCB_COPY_FROM_PARENT,//_xcbscreen.root_depth, - _w, - _xcbscreen.root, - 30, 30, 800, 650, - 1, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - visualId, - mask, - &values[0]); - xcb_flush(_xcbconnection); - windowCaption = _caption; - return true; + } + //mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + //values[0] = _xcbscreen.white_pixel; + + int visualId; + uint eventmask = + 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; + if (_enableOpengl) { + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; + values[0] = _xcbscreen.white_pixel; + values[1] = eventmask; + values[2] = _colormap; + //visualId = _xcbscreen.root_visual; + visualId = _visualID; + } else { + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = _xcbscreen.white_pixel; + values[1] = eventmask; + visualId = _xcbscreen.root_visual; } + Log.d("xcb_create_window - window=", _w, " VisualID=", _visualID); + auto res = xcb_create_window(_xcbconnection, + depth, //_xcbscreen.root_depth, + //XCB_COPY_FROM_PARENT,//_xcbscreen.root_depth, + _w, + _xcbscreen.root, + 30, 30, 800, 650, + 1, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + visualId, + mask, + &values[0]); + xcb_flush(_xcbconnection); + windowCaption = _caption; + return true; + } - private int _imageDx; - private int _imageDy; - void createImage() { - if (_image) { - if (_imageDx == _imageDx && _imageDy == _dy) - return; // already have image of proper size - Log.i("CRXCBScreen::createImage - destroying existing image"); - xcb_image_destroy(_image); - _image = null; - } - _imageDx = _dx; - _imageDy = _dy; - Log.i("CRXCBScreen::createImage ", _dx, "x", _dy); - 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"); - } + private int _imageDx; + private int _imageDy; + void createImage() { + if (_image) { + if (_imageDx == _imageDx && _imageDy == _dy) + return; // already have image of proper size + Log.i("CRXCBScreen::createImage - destroying existing image"); + xcb_image_destroy(_image); + _image = null; } + _imageDx = _dx; + _imageDy = _dy; + Log.i("CRXCBScreen::createImage ", _dx, "x", _dy); + 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 0; - --screen_num, xcb_screen_next(&screen_iter)) { - } - _xcbscreen = screen_iter.data; - } else { - _xcbscreen = xcb_setup_roots_iterator( xcb_get_setup(_xcbconnection) ).data; - } - _xcbscreendepth = xcb_aux_get_depth(_xcbconnection, _xcbscreen); + protected string _caption; - if (_enableOpengl) { - - int versionMajor; - int versionMinor; - if (!glXQueryVersion(_display, - &versionMajor, - &versionMinor)) { - Log.e("Cannot get GLX version"); - } else { - Log.e("GLX version: ", versionMajor, ".", versionMinor); - } - - } + 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() { - - return true; + if (_enableOpengl) { + version(USE_OPENGL) { + import std.c.linux.X11.Xlib; + Log.d("Drawing using opengl ", _dx, "x", _dy, " context=", _context); + //glXMakeContextCurrent(_display, _drawable, _drawable, _context); + glXMakeContextCurrent(_display, _glxwindow, _glxwindow, _context); + glEnable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glViewport(0, 0, _dx, _dy); + Log.d("glClearColor"); + glClearColor(0.2f, 0.4f, 0.9f, 1.0f); + Log.d("glClear"); + glClear(GL_COLOR_BUFFER_BIT); + + import dlangui.graphics.gldrawbuf; + GLDrawBuf buf = new GLDrawBuf(_dx, _dy); + buf.beforeDrawing(); + onDraw(buf); + buf.fillRect(Rect(0, 0, 100, 100), 0x805010); + buf.afterDrawing(); + destroy(buf); + Log.d("Calling glx swap buffers for drawable ", _drawable); + glXSwapBuffers(_display, _drawable); + //glXMakeContextCurrent(_display, _drawable, _drawable, null); + xcb_flush(_xcbconnection); + glXMakeContextCurrent (_display, None, None, null); + glXWaitGL(); + } + } else { + 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); } - 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; - xcb_key_symbols_t * keysyms;// = xcb_key_symbols_alloc(_xcbconnection); - keysyms = xcb_key_symbols_alloc(_xcbconnection); - if (!keysyms) - Log.e("xcb_key_symbols_alloc returned null"); - /* event loop */ - do { - e = xcb_wait_for_event(_xcbconnection); - if (e is null) { - Log.w("NULL event received. Exiting message loop"); + } + + 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; + 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; + if (action == MouseAction.ButtonDown) + flags |= MouseFlag.LButton; + else if (action == MouseAction.ButtonUp) + flags &= ~MouseFlag.LButton; break; + case 2: + button = MouseButton.Middle; + pbuttonDetails = &_mbutton; + if (action == MouseAction.ButtonDown) + flags |= MouseFlag.MButton; + else if (action == MouseAction.ButtonUp) + flags &= ~MouseFlag.MButton; + break; + case 3: + button = MouseButton.Right; + pbuttonDetails = &_rbutton; + if (action == MouseAction.ButtonDown) + flags |= MouseFlag.RButton; + else if (action == MouseAction.ButtonUp) + flags &= ~MouseFlag.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(); + } + } + + uint convertKeyCode(uint keyCode) { + switch (keyCode) { + case XK_BackSpace: + return KeyCode.BACK; + case XK_Tab: + return KeyCode.TAB; + case XK_Linefeed: + case XK_Return: + return KeyCode.RETURN; + case XK_Shift_L: + return KeyCode.LSHIFT; + case XK_Shift_R: + return KeyCode.RSHIFT; + case XK_Control_L: + return KeyCode.LCONTROL; + case XK_Control_R: + return KeyCode.RCONTROL; + case XK_Alt_L: + return KeyCode.LALT; + case XK_Alt_R: + return KeyCode.RALT; + case XK_Pause: + return KeyCode.PAUSE; + case XK_Caps_Lock: + return KeyCode.CAPS; + case XK_Escape: + return KeyCode.ESCAPE; + case XK_KP_Space: + return KeyCode.SPACE; + case XK_KP_Page_Up: + case XK_Page_Up: + return KeyCode.PAGEUP; + case XK_KP_Page_Down: + case XK_Page_Down: + return KeyCode.PAGEDOWN; + case XK_End: + case XK_KP_End: + return KeyCode.END; + case XK_Home: + case XK_KP_Home: + return KeyCode.HOME; + case XK_KP_Left: + case XK_Left: + return KeyCode.LEFT; + case XK_KP_Up: + case XK_Up: + return KeyCode.UP; + case XK_KP_Right: + case XK_Right: + return KeyCode.RIGHT; + case XK_KP_Down: + case XK_Down: + return KeyCode.DOWN; + case XK_Insert: + case XK_KP_Insert: + return KeyCode.INS; + case XK_KP_Delete: + case XK_Delete: + return KeyCode.DEL; + case XK_0: + return KeyCode.KEY_0; + case XK_1: + return KeyCode.KEY_1; + case XK_2: + return KeyCode.KEY_2; + case XK_3: + return KeyCode.KEY_3; + case XK_4: + return KeyCode.KEY_4; + case XK_5: + return KeyCode.KEY_5; + case XK_6: + return KeyCode.KEY_6; + case XK_7: + return KeyCode.KEY_7; + case XK_8: + return KeyCode.KEY_8; + case XK_9: + return KeyCode.KEY_9; + case XK_A: + return KeyCode.KEY_A; + case XK_B: + return KeyCode.KEY_B; + case XK_C: + return KeyCode.KEY_C; + case XK_D: + return KeyCode.KEY_D; + case XK_E: + return KeyCode.KEY_E; + case XK_F: + return KeyCode.KEY_F; + case XK_G: + return KeyCode.KEY_G; + case XK_H: + return KeyCode.KEY_H; + case XK_I: + return KeyCode.KEY_I; + case XK_J: + return KeyCode.KEY_J; + case XK_K: + return KeyCode.KEY_K; + case XK_L: + return KeyCode.KEY_L; + case XK_M: + return KeyCode.KEY_M; + case XK_N: + return KeyCode.KEY_N; + case XK_O: + return KeyCode.KEY_O; + case XK_P: + return KeyCode.KEY_P; + case XK_Q: + return KeyCode.KEY_Q; + case XK_R: + return KeyCode.KEY_R; + case XK_S: + return KeyCode.KEY_S; + case XK_T: + return KeyCode.KEY_T; + case XK_U: + return KeyCode.KEY_U; + case XK_V: + return KeyCode.KEY_V; + case XK_W: + return KeyCode.KEY_W; + case XK_X: + return KeyCode.KEY_X; + case XK_Y: + return KeyCode.KEY_Y; + case XK_Z: + return KeyCode.KEY_Z; + //return KeyCode.LWIN = 0x5b, + //return KeyCode.RWIN = 0x5c, + case XK_KP_0: + return KeyCode.NUM_0; + case XK_KP_1: + return KeyCode.NUM_1; + case XK_KP_2: + return KeyCode.NUM_2; + case XK_KP_3: + return KeyCode.NUM_3; + case XK_KP_4: + return KeyCode.NUM_4; + case XK_KP_5: + return KeyCode.NUM_5; + case XK_KP_6: + return KeyCode.NUM_6; + case XK_KP_7: + return KeyCode.NUM_7; + case XK_KP_8: + return KeyCode.NUM_8; + case XK_KP_9: + return KeyCode.NUM_9; + case XK_asterisk: + return KeyCode.MUL; + case XK_plus: + return KeyCode.ADD; + case XK_slash: + return KeyCode.DIV; + case XK_minus: + return KeyCode.SUB; + case XK_period: + return KeyCode.DECIMAL; + case XK_F1: + return KeyCode.F1; + case XK_F2: + return KeyCode.F2; + case XK_F3: + return KeyCode.F3; + case XK_F4: + return KeyCode.F4; + case XK_F5: + return KeyCode.F5; + case XK_F6: + return KeyCode.F6; + case XK_F7: + return KeyCode.F7; + case XK_F8: + return KeyCode.F8; + case XK_F9: + return KeyCode.F9; + case XK_F10: + return KeyCode.F10; + case XK_F11: + return KeyCode.F11; + case XK_F12: + return KeyCode.F12; + case XK_Num_Lock: + return KeyCode.NUMLOCK; + case XK_Scroll_Lock: + return KeyCode.SCROLL; + default: + return 0x10000 | keyCode; + } + } + + uint convertKeyFlags(uint flags) { + return 0; + } + + bool processKeyEvent(KeyAction action, uint keyCode, uint flags) { + Log.d("processKeyEvent ", action, " x11 key=", keyCode, " x11 flags=", flags); + keyCode = convertKeyCode(keyCode); + flags = convertKeyFlags(flags); + Log.d("processKeyEvent ", action, " converted key=", keyCode, " converted flags=", flags); + bool res = dispatchKeyEvent(new KeyEvent(action, keyCode, flags)); + if (keyCode & 0x10000 && (keyCode & 0xF000) != 0xF000) { + dchar[1] text; + text[0] = keyCode & 0xFFFF; + res = dispatchKeyEvent(new KeyEvent(KeyAction.Text, keyCode, flags, cast(dstring)text)) || res; + } + if (res) { + Log.d("Calling update() after key event"); + invalidate(); + } + return res; + } +} + +private __gshared xcb_connection_t * _xcbconnection; +private __gshared xcb_screen_t * _xcbscreen; +private __gshared ubyte _xcbscreendepth; +private __gshared bool _enableOpengl; +private __gshared std.c.linux.X11.Xlib.Display * _display; + +class XCBPlatform : Platform { + this() { + + } + ~this() { + foreach(ref XCBWindow wnd; _windowMap) { + destroy(wnd); + wnd = null; + } + _windowMap.clear(); + disconnect(); + } + void disconnect() { + /* Cleanup */ + if (_display) { + Log.d("Closing X display"); + std.c.linux.X11.Xlib.XCloseDisplay(_display); + _display = null; + } else if (_xcbconnection) { + Log.d("Closing XCB connection"); + /* close connection to server */ + xcb_disconnect(_xcbconnection); + _xcbconnection = null; + } + } + bool connect() { + + try { + DerelictGL3.load(); + _enableOpengl = true; + } catch (Exception e) { + Log.e("Cannot load opengl library", e); + } + //_enableOpengl = false; // test + // X + import std.c.linux.X11.Xlib; + int default_screen; + + if (_enableOpengl) { + Log.d("Opening display via XLib"); + /* Open Xlib Display */ + _display = XOpenDisplay(null); + if (!_display) + { + Log.e("Failed to open display using Xlib"); + _enableOpengl = false; + } else { + // display is opened + default_screen = DefaultScreen(_display); + Log.d("Opened display ="); + /* Get the XCB connection from the display */ + _xcbconnection = XGetXCBConnection(_display); + if (!_xcbconnection) + { + XCloseDisplay(_display); + _display = null; + Log.e("Failed to get XCB connection from Xlib display"); + _enableOpengl = false; + } else { + /* Acquire event queue ownership */ + XSetEventQueueOwner(_display, XEventQueueOwner.XCBOwnsEventQueue); } - 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"); - 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: { - 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); - XCBWindow window = getWindow(leave.event); + } + } + + if (_xcbconnection is null) { + Log.d("Opening XCB 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 */ + + if (_enableOpengl) { + /* Find XCB screen */ + //xcb_screen_t *screen = null; + xcb_screen_iterator_t screen_iter = + xcb_setup_roots_iterator(xcb_get_setup(_xcbconnection)); + for(int screen_num = default_screen; + screen_iter.rem && screen_num > 0; + --screen_num, xcb_screen_next(&screen_iter)) { + } + _xcbscreen = screen_iter.data; + } else { + _xcbscreen = xcb_setup_roots_iterator( xcb_get_setup(_xcbconnection) ).data; + } + _xcbscreendepth = xcb_aux_get_depth(_xcbconnection, _xcbscreen); + + if (_enableOpengl) { + + int versionMajor; + int versionMinor; + if (!glXQueryVersion(_display, + &versionMajor, + &versionMinor)) { + Log.e("Cannot get GLX version"); + } else { + Log.e("GLX version: ", versionMajor, ".", versionMinor); + } + + } + + + 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; + xcb_key_symbols_t * keysyms;// = xcb_key_symbols_alloc(_xcbconnection); + keysyms = xcb_key_symbols_alloc(_xcbconnection); + if (!keysyms) + Log.e("xcb_key_symbols_alloc returned null"); + /* 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) { // - window.processMouseEvent(MouseAction.Leave, 0, leave.state, leave.event_x, leave.event_y); } else { - Log.w("Received message for unknown window", leave.event); + Log.w("Received message for unknown window", event.window); } - 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); - XCBWindow window = getWindow(kp.event); - if (window !is null) { - //xcb_keysym_t keysym = xcb_key_press_lookup_keysym(keysyms, kp, xcb_lookup_t.xcb_lookup_key_sym_t); - xcb_keysym_t keysym = xcb_key_press_lookup_keysym(keysyms, kp, 2); - Log.d("xcb_key_press_lookup_keysym - key=", kp.detail, " keysym=", keysym); - //xcb_keysym_t keysym = xcb_key_symbols_get_keysym(keysyms, kp.detail, xcb_lookup_t.xcb_lookup_key_sym_t); - window.processKeyEvent(KeyAction.KeyDown, keysym, kp.state); - } - //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); - XCBWindow window = getWindow(kr.event); - if (window !is null) { - //xcb_keysym_t keysym = xcb_key_symbols_get_keysym(keysyms, kr.detail, xcb_lookup_t.xcb_lookup_key_sym_t); - xcb_keysym_t keysym = xcb_key_release_lookup_keysym(keysyms, kr, 2); - window.processKeyEvent(KeyAction.KeyUp, keysym, kr.state); - } - break; - } - default: - Log.v("unknown event: ", e.response_type & ~0x80); break; - } - free(e); - } while(!done); - if (keysyms) - xcb_key_symbols_free(keysyms); - Log.i("exiting message loop"); - return 0; - } - - /// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) - override dstring getClipboardText(bool mouseBuffer = false) { - return ""d; - } - - /// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) - override void setClipboardText(dstring text, bool mouseBuffer = false) { - } - - protected XCBWindow[xcb_window_t] _windowMap; + } + 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"); + 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: { + 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); + 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: { + 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); + XCBWindow window = getWindow(kp.event); + if (window !is null) { + //xcb_keysym_t keysym = xcb_key_press_lookup_keysym(keysyms, kp, xcb_lookup_t.xcb_lookup_key_sym_t); + xcb_keysym_t keysym = xcb_key_press_lookup_keysym(keysyms, kp, 2); + Log.d("xcb_key_press_lookup_keysym - key=", kp.detail, " keysym=", keysym); + //xcb_keysym_t keysym = xcb_key_symbols_get_keysym(keysyms, kp.detail, xcb_lookup_t.xcb_lookup_key_sym_t); + window.processKeyEvent(KeyAction.KeyDown, keysym, kp.state); + } + //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); + XCBWindow window = getWindow(kr.event); + if (window !is null) { + //xcb_keysym_t keysym = xcb_key_symbols_get_keysym(keysyms, kr.detail, xcb_lookup_t.xcb_lookup_key_sym_t); + xcb_keysym_t keysym = xcb_key_release_lookup_keysym(keysyms, kr, 2); + window.processKeyEvent(KeyAction.KeyUp, keysym, kr.state); + } + break; + } + default: + Log.v("unknown event: ", e.response_type & ~0x80); + break; + } + free(e); + } while(!done); + if (keysyms) + xcb_key_symbols_free(keysyms); + Log.i("exiting message loop"); + return 0; } - - // entry point - extern(C) int UIAppMain(string[] args); - int main(string[] args) - { - - setStderrLogger(); - Log.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; - - currentTheme = createDefaultTheme(); - - 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); - Log.d("Destroying XCB platform"); - destroy(xcb); - - currentTheme = null; - drawableCache = null; - imageCache = null; - FontManager.instance = null; - - Log.d("Exiting main"); - - return res; + /// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) + override dstring getClipboardText(bool mouseBuffer = false) { + return ""d; } - + + /// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) + override void setClipboardText(dstring text, bool mouseBuffer = false) { + } + + protected XCBWindow[xcb_window_t] _windowMap; +} + +// entry point +extern(C) int UIAppMain(string[] args); + +int main(string[] args) +{ + + setStderrLogger(); + Log.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; + + currentTheme = createDefaultTheme(); + + 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); + Log.d("Destroying XCB platform"); + destroy(xcb); + + currentTheme = null; + drawableCache = null; + imageCache = null; + FontManager.instance = null; + + Log.d("Exiting main"); + + return res; }