mirror of https://github.com/buggins/dlangui.git
X11 loop cleanup, less redraws. Support for non-resizable windows, minimize, maximize and restore on X11. Add minimize, maximize and restore buttons to example1
This commit is contained in:
parent
ee33115bef
commit
9657e80f04
|
@ -358,6 +358,9 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
|
|
||||||
MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
|
MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
|
||||||
windowItem.add(new Action(30, "MENU_WINDOW_PREFERENCES"));
|
windowItem.add(new Action(30, "MENU_WINDOW_PREFERENCES"));
|
||||||
|
windowItem.add(new Action(31, UIString.fromId("MENU_WINDOW_MINIMIZE")));
|
||||||
|
windowItem.add(new Action(32, UIString.fromId("MENU_WINDOW_MAXIMIZE")));
|
||||||
|
windowItem.add(new Action(33, UIString.fromId("MENU_WINDOW_RESTORE")));
|
||||||
MenuItem helpItem = new MenuItem(new Action(4, "MENU_HELP"c));
|
MenuItem helpItem = new MenuItem(new Action(4, "MENU_HELP"c));
|
||||||
helpItem.add(new Action(40, "MENU_HELP_VIEW_HELP"));
|
helpItem.add(new Action(40, "MENU_HELP_VIEW_HELP"));
|
||||||
MenuItem aboutItem = new MenuItem(new Action(41, "MENU_HELP_ABOUT"));
|
MenuItem aboutItem = new MenuItem(new Action(41, "MENU_HELP_ABOUT"));
|
||||||
|
@ -377,6 +380,15 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
if (a.id == ACTION_FILE_EXIT) {
|
if (a.id == ACTION_FILE_EXIT) {
|
||||||
window.close();
|
window.close();
|
||||||
return true;
|
return true;
|
||||||
|
} else if (a.id == 31) {
|
||||||
|
window.minimizeWindow();
|
||||||
|
return true;
|
||||||
|
} else if (a.id == 32) {
|
||||||
|
window.maximizeWindow();
|
||||||
|
return true;
|
||||||
|
} else if (a.id == 33) {
|
||||||
|
window.restoreWindow();
|
||||||
|
return true;
|
||||||
} else if (a.id == 41) {
|
} else if (a.id == 41) {
|
||||||
window.showMessageBox(UIString.fromRaw("About"d), UIString.fromRaw("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d));
|
window.showMessageBox(UIString.fromRaw("About"d), UIString.fromRaw("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -23,6 +23,9 @@ MENU_VIEW_THEME_DARK=Dark
|
||||||
MENU_VIEW_THEME_CUSTOM1=Custom 1
|
MENU_VIEW_THEME_CUSTOM1=Custom 1
|
||||||
MENU_WINDOW=&Window
|
MENU_WINDOW=&Window
|
||||||
MENU_WINDOW_PREFERENCES=&Preferences
|
MENU_WINDOW_PREFERENCES=&Preferences
|
||||||
|
MENU_WINDOW_MINIMIZE=Minimize
|
||||||
|
MENU_WINDOW_MAXIMIZE=Maximize
|
||||||
|
MENU_WINDOW_RESTORE=Restore
|
||||||
MENU_HELP=&Help
|
MENU_HELP=&Help
|
||||||
MENU_HELP_VIEW_HELP=&View help
|
MENU_HELP_VIEW_HELP=&View help
|
||||||
MENU_HELP_ABOUT=&About
|
MENU_HELP_ABOUT=&About
|
||||||
|
|
|
@ -21,6 +21,9 @@ MENU_VIEW_THEME_DARK=Тёмная
|
||||||
MENU_VIEW_THEME_CUSTOM1=Пример 1
|
MENU_VIEW_THEME_CUSTOM1=Пример 1
|
||||||
MENU_WINDOW=&Окно
|
MENU_WINDOW=&Окно
|
||||||
MENU_WINDOW_PREFERENCES=&Настройки
|
MENU_WINDOW_PREFERENCES=&Настройки
|
||||||
|
MENU_WINDOW_MINIMIZE=Свернуть
|
||||||
|
MENU_WINDOW_MAXIMIZE=Развернуть
|
||||||
|
MENU_WINDOW_RESTORE=Восстановить
|
||||||
MENU_HELP=&Справка
|
MENU_HELP=&Справка
|
||||||
MENU_HELP_VIEW_HELP=&Просмотр справки
|
MENU_HELP_VIEW_HELP=&Просмотр справки
|
||||||
MENU_HELP_ABOUT=&О программе
|
MENU_HELP_ABOUT=&О программе
|
||||||
|
|
|
@ -40,28 +40,43 @@ static if (ENABLE_OPENGL) {
|
||||||
|
|
||||||
//pragma(lib, "X11");
|
//pragma(lib, "X11");
|
||||||
|
|
||||||
private __gshared Display * x11display;
|
|
||||||
private __gshared Display * x11display2;
|
|
||||||
private __gshared int x11screen;
|
|
||||||
private __gshared XIM xim;
|
|
||||||
|
|
||||||
alias XWindow = x11.Xlib.Window;
|
alias XWindow = x11.Xlib.Window;
|
||||||
alias DWindow = dlangui.platforms.common.platform.Window;
|
alias DWindow = dlangui.platforms.common.platform.Window;
|
||||||
|
|
||||||
private __gshared string localClipboardContent;
|
private __gshared
|
||||||
private __gshared Atom atom_UTF8_STRING;
|
{
|
||||||
private __gshared Atom atom_CLIPBOARD;
|
Display * x11display;
|
||||||
private __gshared Atom atom_TARGETS;
|
Display * x11display2;
|
||||||
|
int x11screen;
|
||||||
|
XIM xim;
|
||||||
|
|
||||||
private __gshared Atom atom_WM_PROTOCOLS;
|
string localClipboardContent;
|
||||||
private __gshared Atom atom_WM_DELETE_WINDOW;
|
bool _enableOpengl = false;
|
||||||
|
|
||||||
private __gshared Atom atom_NET_WM_ICON;
|
Cursor[CursorType.Hand + 1] x11cursors;
|
||||||
private __gshared Atom atom_NET_WM_NAME;
|
|
||||||
private __gshared Atom atom_NET_WM_ICON_NAME;
|
|
||||||
|
|
||||||
private __gshared Atom atom_DLANGUI_TIMER_EVENT;
|
Atom atom_UTF8_STRING;
|
||||||
private __gshared Atom atom_DLANGUI_TASK_EVENT;
|
Atom atom_CLIPBOARD;
|
||||||
|
Atom atom_TARGETS;
|
||||||
|
|
||||||
|
Atom atom_WM_PROTOCOLS;
|
||||||
|
Atom atom_WM_DELETE_WINDOW;
|
||||||
|
|
||||||
|
Atom atom_NET_WM_ICON;
|
||||||
|
Atom atom_NET_WM_NAME;
|
||||||
|
Atom atom_NET_WM_ICON_NAME;
|
||||||
|
|
||||||
|
Atom atom_NET_WM_STATE;
|
||||||
|
Atom atom_NET_WM_STATE_MODAL;
|
||||||
|
Atom atom_NET_WM_STATE_MAXIMIZED_VERT;
|
||||||
|
Atom atom_NET_WM_STATE_MAXIMIZED_HORZ;
|
||||||
|
Atom atom_NET_WM_STATE_HIDDEN;
|
||||||
|
Atom atom_NET_WM_STATE_FULLSCREEN;
|
||||||
|
|
||||||
|
Atom atom_DLANGUI_TIMER_EVENT;
|
||||||
|
Atom atom_DLANGUI_TASK_EVENT;
|
||||||
|
Atom atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
||||||
|
}
|
||||||
|
|
||||||
static void setupX11Atoms()
|
static void setupX11Atoms()
|
||||||
{
|
{
|
||||||
|
@ -75,14 +90,18 @@ static void setupX11Atoms()
|
||||||
atom_NET_WM_ICON = XInternAtom(x11display, "_NET_WM_ICON", True);
|
atom_NET_WM_ICON = XInternAtom(x11display, "_NET_WM_ICON", True);
|
||||||
atom_NET_WM_NAME = XInternAtom(x11display, "_NET_WM_NAME", True);
|
atom_NET_WM_NAME = XInternAtom(x11display, "_NET_WM_NAME", True);
|
||||||
atom_NET_WM_ICON_NAME = XInternAtom(x11display, "_NET_WM_ICON_NAME", True);
|
atom_NET_WM_ICON_NAME = XInternAtom(x11display, "_NET_WM_ICON_NAME", True);
|
||||||
|
atom_NET_WM_STATE = XInternAtom(x11display, "_NET_WM_STATE", True);
|
||||||
|
atom_NET_WM_STATE_MODAL = XInternAtom(x11display, "_NET_WM_STATE_MODAL", True);
|
||||||
|
atom_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(x11display, "_NET_WM_STATE_MAXIMIZED_VERT", True);
|
||||||
|
atom_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(x11display, "_NET_WM_STATE_MAXIMIZED_HORZ", True);
|
||||||
|
atom_NET_WM_STATE_HIDDEN = XInternAtom(x11display, "_NET_WM_STATE_HIDDEN", True);
|
||||||
|
atom_NET_WM_STATE_FULLSCREEN = XInternAtom(x11display, "_NET_WM_STATE_FULLSCREEN", True);
|
||||||
|
|
||||||
atom_DLANGUI_TIMER_EVENT = XInternAtom(x11display, "DLANGUI_TIMER_EVENT", False);
|
atom_DLANGUI_TIMER_EVENT = XInternAtom(x11display, "DLANGUI_TIMER_EVENT", False);
|
||||||
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_EVENT", False);
|
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_EVENT", False);
|
||||||
|
atom_DLANGUI_CLOSE_WINDOW_EVENT = XInternAtom(x11display, "DLANGUI_CLOSE_WINDOW_EVENT", False);
|
||||||
}
|
}
|
||||||
|
|
||||||
private __gshared bool _enableOpengl = false;
|
|
||||||
|
|
||||||
private __gshared Cursor[CursorType.Hand + 1] x11cursors;
|
|
||||||
// Cursor font constants
|
// Cursor font constants
|
||||||
enum {
|
enum {
|
||||||
XC_X_cursor=0,
|
XC_X_cursor=0,
|
||||||
|
@ -205,6 +224,12 @@ class X11Window : DWindow {
|
||||||
protected GC _gc;
|
protected GC _gc;
|
||||||
private __gshared XIC xic;
|
private __gshared XIC xic;
|
||||||
|
|
||||||
|
X11Window[] _children;
|
||||||
|
X11Window _parent;
|
||||||
|
|
||||||
|
bool _needRedraw;
|
||||||
|
int _cachedWidth, _cachedHeight;
|
||||||
|
|
||||||
static if (ENABLE_OPENGL) {
|
static if (ENABLE_OPENGL) {
|
||||||
GLXContext _glc;
|
GLXContext _glc;
|
||||||
}
|
}
|
||||||
|
@ -217,9 +242,9 @@ class X11Window : DWindow {
|
||||||
width = 500;
|
width = 500;
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
height = 300;
|
height = 300;
|
||||||
_dx = width;
|
_cachedWidth = _dx = width;
|
||||||
_dy = height;
|
_cachedHeight = _dy = height;
|
||||||
//create(flags);
|
_flags = flags;
|
||||||
|
|
||||||
/* get the colors black and white (see section for details) */
|
/* get the colors black and white (see section for details) */
|
||||||
ulong black, white;
|
ulong black, white;
|
||||||
|
@ -282,18 +307,42 @@ class X11Window : DWindow {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
//XMapWindow(x11display, _win);
|
|
||||||
//XSync(x11display, false);
|
|
||||||
|
|
||||||
//readln();
|
|
||||||
|
|
||||||
/* here is where some properties of the window can be set.
|
|
||||||
The third and fourth items indicate the name which appears
|
|
||||||
at the top of the window and the name of the minimized window
|
|
||||||
respectively.
|
|
||||||
*/
|
|
||||||
windowCaption = caption;
|
windowCaption = caption;
|
||||||
XSetWMProtocols(x11display, _win, &atom_WM_DELETE_WINDOW, 1);
|
XSetWMProtocols(x11display, _win, &atom_WM_DELETE_WINDOW, 1);
|
||||||
|
|
||||||
|
_children.reserve(20);
|
||||||
|
_parent = cast(X11Window) parent;
|
||||||
|
if (_parent)
|
||||||
|
_parent._children ~= this;
|
||||||
|
|
||||||
|
if (!(flags & WindowFlag.Resizable)) {
|
||||||
|
XSizeHints sizeHints;
|
||||||
|
sizeHints.min_width = width;
|
||||||
|
sizeHints.min_height = height;
|
||||||
|
sizeHints.max_width = width;
|
||||||
|
sizeHints.max_height = height;
|
||||||
|
sizeHints.flags = PMaxSize | PMinSize;
|
||||||
|
XSetWMNormalHints(x11display, _win, &sizeHints);
|
||||||
|
}
|
||||||
|
if (flags & WindowFlag.Fullscreen) {
|
||||||
|
if (atom_NET_WM_STATE_FULLSCREEN != None) {
|
||||||
|
changeWindowState(_NET_WM_STATE_ADD, atom_NET_WM_STATE_FULLSCREEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.w("Missing _NET_WM_STATE_FULLSCREEN atom");
|
||||||
|
}
|
||||||
|
if (flags & WindowFlag.Modal) {
|
||||||
|
if (_parent) {
|
||||||
|
XSetTransientForHint(x11display, _win, _parent._win);
|
||||||
|
} else {
|
||||||
|
Log.w("Top-level modal window");
|
||||||
|
}
|
||||||
|
if (atom_NET_WM_STATE_MODAL != None) {
|
||||||
|
changeWindowState(_NET_WM_STATE_ADD, atom_NET_WM_STATE_MODAL);
|
||||||
|
} else {
|
||||||
|
Log.w("Missing _NET_WM_STATE_MODAL atom");
|
||||||
|
}
|
||||||
|
}
|
||||||
/* this routine determines which types of input are allowed in
|
/* this routine determines which types of input are allowed in
|
||||||
the input. see the appropriate section for details...
|
the input. see the appropriate section for details...
|
||||||
*/
|
*/
|
||||||
|
@ -321,15 +370,26 @@ class X11Window : DWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
|
debug Log.d("Destroying X11 window");
|
||||||
if (timer) {
|
if (timer) {
|
||||||
timer.stop();
|
timer.stop();
|
||||||
}
|
}
|
||||||
|
if (_parent) {
|
||||||
|
import std.algorithm : countUntil, remove;
|
||||||
|
ptrdiff_t index = countUntil(_parent._children,this);
|
||||||
|
if (index > -1 ) {
|
||||||
|
_parent._children = _parent._children.remove(index);
|
||||||
|
}
|
||||||
|
_parent = null;
|
||||||
|
}
|
||||||
static if (ENABLE_OPENGL) {
|
static if (ENABLE_OPENGL) {
|
||||||
if (_glc) {
|
if (_glc) {
|
||||||
glXDestroyContext(x11display, _glc);
|
glXDestroyContext(x11display, _glc);
|
||||||
_glc = null;
|
_glc = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_drawbuf)
|
||||||
|
destroy(_drawbuf);
|
||||||
if (_gc) {
|
if (_gc) {
|
||||||
XFreeGC(x11display, _gc);
|
XFreeGC(x11display, _gc);
|
||||||
_gc = null;
|
_gc = null;
|
||||||
|
@ -378,6 +438,79 @@ class X11Window : DWindow {
|
||||||
_mainWidget.setFocus();
|
_mainWidget.setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final void changeWindowState(int action, Atom firstProperty, Atom secondProperty = None) nothrow
|
||||||
|
{
|
||||||
|
XEvent ev;
|
||||||
|
memset(&ev, 0, ev.sizeof);
|
||||||
|
ev.xany.type = ClientMessage;
|
||||||
|
ev.xclient.window = _win;
|
||||||
|
ev.xclient.message_type = atom_NET_WM_STATE;
|
||||||
|
ev.xclient.format = 32;
|
||||||
|
ev.xclient.data.l[0] = action;
|
||||||
|
ev.xclient.data.l[1] = firstProperty;
|
||||||
|
if (secondProperty != None)
|
||||||
|
ev.xclient.data.l[2] = secondProperty;
|
||||||
|
ev.xclient.data.l[3] = 0;
|
||||||
|
XSendEvent(x11display, RootWindow(x11display, x11screen), false, SubstructureNotifyMask|SubstructureRedirectMask, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected enum {
|
||||||
|
_NET_WM_STATE_REMOVE = 0,
|
||||||
|
_NET_WM_STATE_ADD,
|
||||||
|
_NET_WM_STATE_TOGGLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool setWindowState(WindowState newState, bool activate = false, Rect newWindowRect = RECT_VALUE_IS_NOT_SET) {
|
||||||
|
if (_win == None) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool result = false;
|
||||||
|
switch(newState) {
|
||||||
|
case WindowState.maximized:
|
||||||
|
if (atom_NET_WM_STATE != None && atom_NET_WM_STATE_MAXIMIZED_HORZ != None && atom_NET_WM_STATE_MAXIMIZED_VERT != None) {
|
||||||
|
changeWindowState(_NET_WM_STATE_ADD, atom_NET_WM_STATE_MAXIMIZED_HORZ, atom_NET_WM_STATE_MAXIMIZED_VERT);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WindowState.minimized:
|
||||||
|
if (atom_NET_WM_STATE != None && atom_NET_WM_STATE_HIDDEN != None) {
|
||||||
|
changeWindowState(_NET_WM_STATE_ADD, atom_NET_WM_STATE_HIDDEN);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WindowState.hidden:
|
||||||
|
XUnmapWindow(x11display, _win);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case WindowState.normal:
|
||||||
|
if (atom_NET_WM_STATE != None &&
|
||||||
|
atom_NET_WM_STATE_MAXIMIZED_HORZ != None &&
|
||||||
|
atom_NET_WM_STATE_MAXIMIZED_VERT != None &&
|
||||||
|
atom_NET_WM_STATE_HIDDEN != None)
|
||||||
|
{
|
||||||
|
changeWindowState(_NET_WM_STATE_REMOVE, atom_NET_WM_STATE_MAXIMIZED_HORZ, atom_NET_WM_STATE_MAXIMIZED_VERT);
|
||||||
|
changeWindowState(_NET_WM_STATE_REMOVE, atom_NET_WM_STATE_HIDDEN);
|
||||||
|
changeWindowState(_NET_WM_STATE_REMOVE, atom_NET_WM_STATE_FULLSCREEN);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WindowState.fullscreen:
|
||||||
|
if (atom_NET_WM_STATE != None && atom_NET_WM_STATE_FULLSCREEN != None) {
|
||||||
|
changeWindowState(_NET_WM_STATE_ADD, atom_NET_WM_STATE_FULLSCREEN);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (activate) {
|
||||||
|
XMapRaised(x11display, _win);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
XFlush(x11display);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
override @property dstring windowCaption() {
|
override @property dstring windowCaption() {
|
||||||
return _caption;
|
return _caption;
|
||||||
}
|
}
|
||||||
|
@ -408,6 +541,7 @@ class X11Window : DWindow {
|
||||||
immutable int iconw = 32;
|
immutable int iconw = 32;
|
||||||
immutable int iconh = 32;
|
immutable int iconh = 32;
|
||||||
ColorDrawBuf iconDraw = new ColorDrawBuf(iconw, iconh);
|
ColorDrawBuf iconDraw = new ColorDrawBuf(iconw, iconh);
|
||||||
|
scope(exit) destroy(iconDraw);
|
||||||
iconDraw.fill(0xFF000000);
|
iconDraw.fill(0xFF000000);
|
||||||
iconDraw.drawRescaled(Rect(0, 0, iconw, iconh), icon, Rect(0, 0, icon.width, icon.height));
|
iconDraw.drawRescaled(Rect(0, 0, iconw, iconh), icon, Rect(0, 0, icon.width, icon.height));
|
||||||
iconDraw.invertAndPreMultiplyAlpha();
|
iconDraw.invertAndPreMultiplyAlpha();
|
||||||
|
@ -420,31 +554,19 @@ class X11Window : DWindow {
|
||||||
}
|
}
|
||||||
XChangeProperty(x11display, _win, atom_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, cast(ubyte*)propData.ptr, cast(int)propData.length);
|
XChangeProperty(x11display, _win, atom_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, cast(ubyte*)propData.ptr, cast(int)propData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// request window redraw
|
/// request window redraw
|
||||||
override void invalidate() {
|
override void invalidate() {
|
||||||
debug(x11) Log.d("Window.invalidate()");
|
if (!_needRedraw) {
|
||||||
XEvent ev;
|
debug(x11) Log.d("Window.invalidate()");
|
||||||
memset(&ev, 0, ev.sizeof);
|
_needRedraw = true;
|
||||||
ev.type = Expose;
|
|
||||||
ev.xexpose.window = _win;
|
|
||||||
|
|
||||||
static if (true) {
|
|
||||||
//ev.xclient.display = x11display2;
|
|
||||||
//ev.xclient.message_type = atom_DLANGUI_TASK_EVENT;
|
|
||||||
//ev.xclient.format = 32;
|
|
||||||
//ev.xclient.data.l[0] = event.uniqueId;
|
|
||||||
XLockDisplay(x11display2);
|
|
||||||
XSendEvent(x11display2, _win, false, StructureNotifyMask, &ev);
|
|
||||||
XFlush(x11display2);
|
|
||||||
XUnlockDisplay(x11display2);
|
|
||||||
} else {
|
|
||||||
XSendEvent(x11display, _win, false, ExposureMask, &ev);
|
|
||||||
XFlush(x11display);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// close window
|
/// close window
|
||||||
override void close() {
|
override void close() {
|
||||||
|
Log.d("X11Window.close()");
|
||||||
|
_platform.closeWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorDrawBuf _drawbuf;
|
ColorDrawBuf _drawbuf;
|
||||||
|
@ -484,7 +606,7 @@ class X11Window : DWindow {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
_drawbuf.width,
|
_drawbuf.width,
|
||||||
_drawbuf.height);
|
_drawbuf.height);
|
||||||
XFlush(x11display);
|
//XFlush(x11display); // no need to XFlush since it will be called in event loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,21 +631,21 @@ class X11Window : DWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void processExpose() {
|
void redraw() {
|
||||||
XWindowAttributes window_attributes_return;
|
_needRedraw = false;
|
||||||
XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
//Use values cached by ConfigureNotify to avoid XGetWindowAttributes call.
|
||||||
|
//XWindowAttributes window_attributes_return;
|
||||||
|
//XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
||||||
//Log.d(format("XGetWindowAttributes reported size %d, %d", window_attributes_return.width, window_attributes_return.height));
|
//Log.d(format("XGetWindowAttributes reported size %d, %d", window_attributes_return.width, window_attributes_return.height));
|
||||||
int width = window_attributes_return.width;
|
immutable width = _cachedWidth;
|
||||||
int height = window_attributes_return.height;
|
immutable height = _cachedHeight;
|
||||||
if (width > 0 && height > 0)
|
if (width > 0 && height > 0)
|
||||||
onResize(width, height);
|
onResize(width, height);
|
||||||
debug(x11) Log.d(format("processExpose(%d, %d)", width, height));
|
debug(x11) Log.d(format("redraw(%d, %d)", width, height));
|
||||||
if (_enableOpengl)
|
if (_enableOpengl)
|
||||||
drawUsingOpengl();
|
drawUsingOpengl();
|
||||||
else
|
else
|
||||||
drawUsingBitmap();
|
drawUsingBitmap();
|
||||||
//Log.d("processExpose - drawing finished");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ButtonDetails _lbutton;
|
protected ButtonDetails _lbutton;
|
||||||
|
@ -935,12 +1057,11 @@ class X11Window : DWindow {
|
||||||
TimerThread timer;
|
TimerThread timer;
|
||||||
private long _nextExpectedTimerTs;
|
private long _nextExpectedTimerTs;
|
||||||
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
/// schedule timer for interval in milliseconds - call window.onTimer when finished
|
/// schedule timer for interval in milliseconds - call window.onTimer when finished
|
||||||
override protected void scheduleSystemTimer(long intervalMillis) {
|
override protected void scheduleSystemTimer(long intervalMillis) {
|
||||||
if (!timer) {
|
if (!timer) {
|
||||||
timer = new TimerThread(delegate() {
|
timer = new TimerThread(delegate() {
|
||||||
|
XEvent ev;
|
||||||
memset(&ev, 0, ev.sizeof);
|
memset(&ev, 0, ev.sizeof);
|
||||||
//ev.xclient = XClientMessageEvent.init;
|
//ev.xclient = XClientMessageEvent.init;
|
||||||
ev.xclient.type = ClientMessage;
|
ev.xclient.type = ClientMessage;
|
||||||
|
@ -1051,7 +1172,19 @@ class X11Platform : Platform {
|
||||||
* Closes window earlier created with createWindow()
|
* Closes window earlier created with createWindow()
|
||||||
*/
|
*/
|
||||||
override void closeWindow(DWindow w) {
|
override void closeWindow(DWindow w) {
|
||||||
_windowMap.remove((cast(X11Window)w)._win);
|
X11Window window = cast(X11Window)w;
|
||||||
|
XEvent ev;
|
||||||
|
memset(&ev, 0, ev.sizeof);
|
||||||
|
ev.xclient.type = ClientMessage;
|
||||||
|
ev.xclient.message_type = atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
||||||
|
ev.xclient.window = window._win;
|
||||||
|
ev.xclient.display = x11display2;
|
||||||
|
ev.xclient.format = 32;
|
||||||
|
Log.d("Sending close window event");
|
||||||
|
XLockDisplay(x11display2);
|
||||||
|
XSendEvent(x11display2, window._win, false, StructureNotifyMask, &ev);
|
||||||
|
XFlush(x11display2);
|
||||||
|
XUnlockDisplay(x11display2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleTimers() {
|
bool handleTimers() {
|
||||||
|
@ -1065,6 +1198,10 @@ class X11Platform : Platform {
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final bool allWindowsClosed() {
|
||||||
|
return _windowMap.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts application message loop.
|
* Starts application message loop.
|
||||||
*
|
*
|
||||||
|
@ -1077,8 +1214,6 @@ class X11Platform : Platform {
|
||||||
char[255] text; /* a char buffer for KeyPress Events */
|
char[255] text; /* a char buffer for KeyPress Events */
|
||||||
|
|
||||||
Log.d("enterMessageLoop()");
|
Log.d("enterMessageLoop()");
|
||||||
/* look for events forever... */
|
|
||||||
bool finished = false;
|
|
||||||
XComposeStatus compose;
|
XComposeStatus compose;
|
||||||
|
|
||||||
import core.sys.posix.sys.select;
|
import core.sys.posix.sys.select;
|
||||||
|
@ -1086,23 +1221,27 @@ class X11Platform : Platform {
|
||||||
fd_set fdSet;
|
fd_set fdSet;
|
||||||
FD_ZERO(&fdSet);
|
FD_ZERO(&fdSet);
|
||||||
FD_SET(x11displayFd, &fdSet);
|
FD_SET(x11displayFd, &fdSet);
|
||||||
while(!finished) {
|
scope(exit) FD_ZERO(&fdSet);
|
||||||
/* get the next event and stuff it into our event variable.
|
while(!allWindowsClosed()) {
|
||||||
Note: only events we set the mask for are detected!
|
// Note: only events we set the mask for are detected!
|
||||||
*/
|
foreach(win; _windowMap) {
|
||||||
//bool timersHandled = handleTimers();
|
if (win._needRedraw) {
|
||||||
//if (timersHandled)
|
win.redraw();
|
||||||
//XFlush(x11display);
|
}
|
||||||
//while (XEventsQueued(x11display, QueuedAfterFlush)) {//QueuedAfterFlush
|
}
|
||||||
XFlush(x11display);
|
XFlush(x11display);
|
||||||
int eventsInQueue = XEventsQueued(x11display, QueuedAlready);
|
int eventsInQueue = XEventsQueued(x11display, QueuedAlready);
|
||||||
if (!eventsInQueue) {
|
if (!eventsInQueue) {
|
||||||
timeval zeroTime;
|
import core.stdc.errno;
|
||||||
auto selectResult = select(x11displayFd + 1, &fdSet, null, null, &zeroTime);
|
int selectResult;
|
||||||
|
do {
|
||||||
|
timeval zeroTime;
|
||||||
|
selectResult = select(x11displayFd + 1, &fdSet, null, null, &zeroTime);
|
||||||
|
} while(selectResult == -1 && errno == EINTR);
|
||||||
if (selectResult < 0) {
|
if (selectResult < 0) {
|
||||||
Log.e("select error");
|
Log.e("X11: display fd select error");
|
||||||
} else if (selectResult == 1) {
|
} else if (selectResult == 1) {
|
||||||
Log.d("Pending");
|
Log.d("X11: XPending");
|
||||||
eventsInQueue = XPending(x11display);
|
eventsInQueue = XPending(x11display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1112,21 +1251,26 @@ class X11Platform : Platform {
|
||||||
}
|
}
|
||||||
foreach(eventIndex; 0..eventsInQueue)
|
foreach(eventIndex; 0..eventsInQueue)
|
||||||
{
|
{
|
||||||
//Thread.sleep(dur!("msecs")(10));
|
if (allWindowsClosed())
|
||||||
//continue;
|
break;
|
||||||
XNextEvent(x11display, &event);
|
XNextEvent(x11display, &event);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
case ConfigureNotify:
|
||||||
|
X11Window w = findWindow(event.xconfigure.window);
|
||||||
|
if (w) {
|
||||||
|
w._cachedWidth = event.xconfigure.width;
|
||||||
|
w._cachedHeight = event.xconfigure.height;
|
||||||
|
} else {
|
||||||
|
Log.e("ConfigureNotify: Window not found");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Expose:
|
case Expose:
|
||||||
if (event.xexpose.count == 0) {
|
if (event.xexpose.count == 0) {
|
||||||
/* the window was exposed redraw it! */
|
|
||||||
//redraw();
|
|
||||||
X11Window w = findWindow(event.xexpose.window);
|
X11Window w = findWindow(event.xexpose.window);
|
||||||
if (w) {
|
if (w) {
|
||||||
|
w.invalidate();
|
||||||
w.processExpose();
|
|
||||||
} else {
|
} else {
|
||||||
Log.e("Window not found");
|
Log.e("Expose: Window not found");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d("Expose: non-0 count");
|
Log.d("Expose: non-0 count");
|
||||||
|
@ -1176,8 +1320,6 @@ class X11Platform : Platform {
|
||||||
//event.xkey.keycode,
|
//event.xkey.keycode,
|
||||||
event.xkey.state);
|
event.xkey.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
|
@ -1244,56 +1386,37 @@ class X11Platform : Platform {
|
||||||
case CreateNotify:
|
case CreateNotify:
|
||||||
Log.d("X11: CreateNotify event");
|
Log.d("X11: CreateNotify event");
|
||||||
X11Window w = findWindow(event.xcreatewindow.window);
|
X11Window w = findWindow(event.xcreatewindow.window);
|
||||||
if (w) {
|
if (!w) {
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
Log.d("X11: DestroyNotify event");
|
Log.d("X11: DestroyNotify event");
|
||||||
X11Window w = findWindow(event.xdestroywindow.window);
|
|
||||||
if (w) {
|
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ResizeRequest:
|
case ResizeRequest:
|
||||||
Log.d("X11: ResizeRequest event");
|
Log.d("X11: ResizeRequest event");
|
||||||
X11Window w = findWindow(event.xresizerequest.window);
|
X11Window w = findWindow(event.xresizerequest.window);
|
||||||
if (w) {
|
if (!w) {
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
Log.d("X11: FocusIn event");
|
Log.d("X11: FocusIn event");
|
||||||
X11Window w = findWindow(event.xfocus.window);
|
X11Window w = findWindow(event.xfocus.window);
|
||||||
if (w) {
|
if (!w) {
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
Log.d("X11: FocusOut event");
|
Log.d("X11: FocusOut event");
|
||||||
X11Window w = findWindow(event.xfocus.window);
|
X11Window w = findWindow(event.xfocus.window);
|
||||||
if (w) {
|
if (!w) {
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeymapNotify:
|
case KeymapNotify:
|
||||||
Log.d("X11: KeymapNotify event");
|
Log.d("X11: KeymapNotify event");
|
||||||
X11Window w = findWindow(event.xkeymap.window);
|
X11Window w = findWindow(event.xkeymap.window);
|
||||||
if (w) {
|
|
||||||
//w.processExpose();
|
|
||||||
} else {
|
|
||||||
Log.e("Window not found");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
debug(x11) Log.d("X11: ClientMessage event");
|
debug(x11) Log.d("X11: ClientMessage event");
|
||||||
|
@ -1307,9 +1430,12 @@ class X11Platform : Platform {
|
||||||
Log.d("Handling WM_PROTOCOLS");
|
Log.d("Handling WM_PROTOCOLS");
|
||||||
if ((event.xclient.format == 32) && (event.xclient.data.l[0]) == atom_WM_DELETE_WINDOW) {
|
if ((event.xclient.format == 32) && (event.xclient.data.l[0]) == atom_WM_DELETE_WINDOW) {
|
||||||
Log.d("Handling WM_DELETE_WINDOW");
|
Log.d("Handling WM_DELETE_WINDOW");
|
||||||
closeWindow(w);
|
_windowMap.remove(w._win);
|
||||||
destroy(w);
|
destroy(w);
|
||||||
}
|
}
|
||||||
|
} else if (event.xclient.message_type == atom_DLANGUI_CLOSE_WINDOW_EVENT) {
|
||||||
|
_windowMap.remove(w._win);
|
||||||
|
destroy(w);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e("Window not found");
|
Log.e("Window not found");
|
||||||
|
@ -1319,11 +1445,6 @@ class X11Platform : Platform {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_windowMap.length == 0) {
|
|
||||||
finished = true;
|
|
||||||
}
|
|
||||||
//Thread.sleep(dur!("msecs")(10));
|
|
||||||
//XFlush(x11display);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue