mirror of https://github.com/buggins/dlangui.git
Merge branch 'master' of github.com:buggins/dlangui
This commit is contained in:
commit
132bfd8c2a
|
@ -266,7 +266,9 @@ extern (C) int UIAppMain(string[] args) {
|
|||
//}
|
||||
|
||||
// create window
|
||||
Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable, 800, 700);
|
||||
//Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable, 800, 700);
|
||||
// Expand window size if content is bigger than 800, 700 (change to above version if you want scrollbars and 800, 700 size)
|
||||
Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable | WindowFlag.ExpandSize, 800, 700);
|
||||
// here you can see window or content resize mode
|
||||
//Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable, 400, 400);
|
||||
//window.windowOrContentResizeMode = WindowOrContentResizeMode.resizeWindow;
|
||||
|
|
|
@ -56,6 +56,8 @@ enum WindowFlag : uint {
|
|||
MeasureSize = 8,
|
||||
/// window without decorations
|
||||
Borderless = 16,
|
||||
/// expand window size if main widget minimal size is greater than size defined in window constructor
|
||||
ExpandSize = 32,
|
||||
}
|
||||
|
||||
/// Window states
|
||||
|
@ -333,9 +335,9 @@ class Window : CustomEventTarget {
|
|||
@property bool caretReplace() { return _caretReplace; }
|
||||
|
||||
// window content resize mode
|
||||
protected WindowOrContentResizeMode _windowOrContentResizeMode = WindowOrContentResizeMode.resizeWindow;
|
||||
//protected WindowOrContentResizeMode _windowOrContentResizeMode = WindowOrContentResizeMode.resizeWindow;
|
||||
//protected WindowOrContentResizeMode _windowOrContentResizeMode = WindowOrContentResizeMode.shrinkWidgets;
|
||||
//protected WindowOrContentResizeMode _windowOrContentResizeMode = WindowOrContentResizeMode.scrollWindow;
|
||||
protected WindowOrContentResizeMode _windowOrContentResizeMode = WindowOrContentResizeMode.scrollWindow;
|
||||
|
||||
@property WindowOrContentResizeMode windowOrContentResizeMode() {return _windowOrContentResizeMode; }
|
||||
@property void windowOrContentResizeMode(WindowOrContentResizeMode newMode) {
|
||||
|
@ -466,7 +468,7 @@ class Window : CustomEventTarget {
|
|||
void adjustWindowOrContentSize(int minContentWidth, int minContentHeight) {
|
||||
_minContentWidth = minContentWidth;
|
||||
_minContentHeight = minContentHeight;
|
||||
if (_windowOrContentResizeMode == WindowOrContentResizeMode.resizeWindow)
|
||||
if (_windowOrContentResizeMode == WindowOrContentResizeMode.resizeWindow || flags & WindowFlag.ExpandSize)
|
||||
resizeWindow(Point(max(_windowRect.right, minContentWidth), max(_windowRect.bottom, minContentHeight)));
|
||||
updateWindowOrContentSize();
|
||||
}
|
||||
|
|
|
@ -412,7 +412,19 @@ class SDLWindow : Window {
|
|||
if (_windowState != WindowState.normal) {
|
||||
SDL_RestoreWindow(_win);
|
||||
version(linux) {
|
||||
// some SDL versions, reset windows size and position to values from create window (SDL 2.0.4) on linux (don't know how it works on macOS)
|
||||
// On linux with Cinnamon desktop, changing window state from for example minimized reset windows size
|
||||
// and/or position to values from create window (last tested on Cinamon 3.4.6 with SDL 2.0.4)
|
||||
//
|
||||
// Steps to reproduce:
|
||||
// Need app with two windows - dlangide for example.
|
||||
// 1. Comment this fix
|
||||
// 2. dub run --force
|
||||
// 3. After first window appear move it and/or change window size
|
||||
// 4. Click on button to open file
|
||||
// 5. Click on window icon minimize in open file dialog
|
||||
// 6. Restore window clicking on taskbar
|
||||
// 7. The first main window has old position/size
|
||||
// Xfce works OK without this fix
|
||||
if (newWindowRect.bottom == int.min && newWindowRect.right == int.min)
|
||||
SDL_SetWindowSize(_win, _windowRect.right, _windowRect.bottom);
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ private __gshared
|
|||
Atom atom_DLANGUI_TASK_EVENT;
|
||||
Atom atom_DLANGUI_CLOSE_WINDOW_EVENT;
|
||||
Atom atom_DLANGUI_CLIPBOARD_BUFFER;
|
||||
Atom atom_DLANGUI_REDRAW_EVENT;
|
||||
}
|
||||
|
||||
static void setupX11Atoms()
|
||||
|
@ -127,6 +128,7 @@ static void setupX11Atoms()
|
|||
atom_DLANGUI_TASK_EVENT = XInternAtom(x11display, "DLANGUI_TASK_EVENT", False);
|
||||
atom_DLANGUI_CLOSE_WINDOW_EVENT = XInternAtom(x11display, "DLANGUI_CLOSE_WINDOW_EVENT", False);
|
||||
atom_DLANGUI_CLIPBOARD_BUFFER = XInternAtom(x11display, "DLANGUI_CLIPBOARD_BUFFER", False);
|
||||
atom_DLANGUI_REDRAW_EVENT = XInternAtom(x11display, "DLANGUI_REDRAW_EVENT", False);
|
||||
}
|
||||
|
||||
// Cursor font constants
|
||||
|
@ -254,7 +256,6 @@ class X11Window : DWindow {
|
|||
X11Window[] _children;
|
||||
X11Window _parent;
|
||||
|
||||
bool _needRedraw;
|
||||
int _cachedWidth, _cachedHeight;
|
||||
|
||||
static if (ENABLE_OPENGL) {
|
||||
|
@ -440,11 +441,19 @@ class X11Window : DWindow {
|
|||
}
|
||||
}
|
||||
|
||||
private bool hasVisibleModalChild() {
|
||||
foreach (X11Window w;_children) {
|
||||
if (w.flags & WindowFlag.Modal && w._windowState != WindowState.hidden)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// show window
|
||||
override void show() {
|
||||
Log.d("X11Window.show");
|
||||
XMapRaised(x11display, _win);
|
||||
XFlush(x11display);
|
||||
|
||||
static if (ENABLE_OPENGL) {
|
||||
if (_enableOpengl) {
|
||||
_glc = glXCreateContext(x11display, x11visual, null, GL_TRUE);
|
||||
|
@ -476,6 +485,7 @@ class X11Window : DWindow {
|
|||
|
||||
_mainWidget.setFocus();
|
||||
}
|
||||
XFlush(x11display);
|
||||
}
|
||||
|
||||
override protected void handleWindowStateChange(WindowState newState, Rect newWindowRect = RECT_VALUE_IS_NOT_SET) {
|
||||
|
@ -652,12 +662,18 @@ class X11Window : DWindow {
|
|||
XChangeProperty(x11display, _win, atom_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, cast(ubyte*)propData.ptr, cast(int)propData.length);
|
||||
}
|
||||
|
||||
uint _lastRedrawEventCode;
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
if (!_needRedraw) {
|
||||
debug(x11) Log.d("Window.invalidate()");
|
||||
_needRedraw = true;
|
||||
}
|
||||
XEvent ev;
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.message_type = atom_DLANGUI_REDRAW_EVENT;
|
||||
ev.xclient.window = _win;
|
||||
ev.xclient.display = x11display;
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = ++_lastRedrawEventCode;
|
||||
XSendEvent(x11display, _win, false, StructureNotifyMask, &ev);
|
||||
XFlush(x11display);
|
||||
}
|
||||
|
||||
/// close window
|
||||
|
@ -729,7 +745,7 @@ class X11Window : DWindow {
|
|||
}
|
||||
|
||||
void redraw() {
|
||||
_needRedraw = false;
|
||||
_lastRedrawEventCode = 0;
|
||||
//Use values cached by ConfigureNotify to avoid XGetWindowAttributes call.
|
||||
//XWindowAttributes window_attributes_return;
|
||||
//XGetWindowAttributes(x11display, _win, &window_attributes_return);
|
||||
|
@ -749,14 +765,39 @@ class X11Window : DWindow {
|
|||
protected ButtonDetails _mbutton;
|
||||
protected ButtonDetails _rbutton;
|
||||
|
||||
ushort convertMouseFlags(uint flags) {
|
||||
// x11 gives flags from time prior event so if left button is pressed there is not Button1Mask
|
||||
ushort convertMouseFlags(uint flags, MouseButton btn, bool pressed) {
|
||||
ushort res = 0;
|
||||
if (flags & Button1Mask)
|
||||
res |= MouseFlag.LButton;
|
||||
if (flags & Button2Mask)
|
||||
res |= MouseFlag.RButton;
|
||||
if (flags & Button3Mask)
|
||||
res |= MouseFlag.MButton;
|
||||
if (btn == MouseButton.Left) {
|
||||
if (pressed)
|
||||
res |= MouseFlag.LButton;
|
||||
else
|
||||
res &= ~MouseFlag.LButton;
|
||||
}
|
||||
else
|
||||
if (flags & Button1Mask)
|
||||
res |= MouseFlag.LButton;
|
||||
|
||||
if (btn == MouseButton.Middle) {
|
||||
if (pressed)
|
||||
res |= MouseFlag.MButton;
|
||||
else
|
||||
res &= ~MouseFlag.MButton;
|
||||
}
|
||||
else
|
||||
if (flags & Button2Mask)
|
||||
res |= MouseFlag.MButton;
|
||||
|
||||
if (btn == MouseButton.Right) {
|
||||
if (pressed)
|
||||
res |= MouseFlag.RButton;
|
||||
else
|
||||
res &= ~MouseFlag.RButton;
|
||||
}
|
||||
else
|
||||
if (flags & Button3Mask)
|
||||
res |= MouseFlag.RButton;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -764,9 +805,9 @@ class X11Window : DWindow {
|
|||
if (button == Button1)
|
||||
return MouseButton.Left;
|
||||
if (button == Button2)
|
||||
return MouseButton.Right;
|
||||
if (button == Button3)
|
||||
return MouseButton.Middle;
|
||||
if (button == Button3)
|
||||
return MouseButton.Right;
|
||||
return MouseButton.None;
|
||||
}
|
||||
|
||||
|
@ -794,7 +835,9 @@ class X11Window : DWindow {
|
|||
if (wheelDelta)
|
||||
event = new MouseEvent(action, MouseButton.None, lastFlags, lastx, lasty, wheelDelta);
|
||||
} else {
|
||||
lastFlags = convertMouseFlags(state);
|
||||
MouseButton btn = convertMouseButton(button);
|
||||
lastFlags = convertMouseFlags(state, btn, action == MouseAction.ButtonDown);
|
||||
|
||||
if (_keyFlags & KeyFlag.Shift)
|
||||
lastFlags |= MouseFlag.Shift;
|
||||
if (_keyFlags & KeyFlag.Control)
|
||||
|
@ -803,7 +846,6 @@ class X11Window : DWindow {
|
|||
lastFlags |= MouseFlag.Alt;
|
||||
lastx = cast(short)x;
|
||||
lasty = cast(short)y;
|
||||
MouseButton btn = convertMouseButton(button);
|
||||
event = new MouseEvent(action, btn, lastFlags, lastx, lasty);
|
||||
}
|
||||
if (event) {
|
||||
|
@ -824,6 +866,7 @@ class X11Window : DWindow {
|
|||
event.lbutton = _lbutton;
|
||||
event.rbutton = _rbutton;
|
||||
event.mbutton = _mbutton;
|
||||
|
||||
bool res = dispatchMouseEvent(event);
|
||||
if (res) {
|
||||
debug(mouse) Log.d("Calling update() after mouse event");
|
||||
|
@ -1237,7 +1280,6 @@ class X11Platform : Platform {
|
|||
}
|
||||
|
||||
private X11Window[XWindow] _windowMap;
|
||||
private X11Window[] _windowList;
|
||||
|
||||
/**
|
||||
* create window
|
||||
|
@ -1255,7 +1297,6 @@ class X11Platform : Platform {
|
|||
int newheight = height;
|
||||
X11Window window = new X11Window(this, windowCaption, parent, flags, newwidth, newheight);
|
||||
_windowMap[window._win] = window;
|
||||
_windowList ~= window;
|
||||
return window;
|
||||
}
|
||||
|
||||
|
@ -1284,17 +1325,6 @@ class X11Platform : Platform {
|
|||
XSendEvent(x11display2, window._win, false, StructureNotifyMask, &ev);
|
||||
XFlush(x11display2);
|
||||
XUnlockDisplay(x11display2);
|
||||
|
||||
for (uint i = 0; i < _windowList.length; i++) {
|
||||
if (w is _windowList[i]) {
|
||||
for (uint j = i; j + 1 < _windowList.length; j++)
|
||||
_windowList[j] = _windowList[j + 1];
|
||||
_windowList[$ - 1] = null;
|
||||
_windowList.length--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool handleTimers() {
|
||||
|
@ -1312,7 +1342,7 @@ class X11Platform : Platform {
|
|||
return _windowMap.length == 0;
|
||||
}
|
||||
|
||||
protected int numberOfPendingEvents()
|
||||
protected int numberOfPendingEvents(int msecs = 10)
|
||||
{
|
||||
import core.sys.posix.sys.select;
|
||||
int x11displayFd = ConnectionNumber(x11display);
|
||||
|
@ -1326,13 +1356,14 @@ class X11Platform : Platform {
|
|||
import core.stdc.errno;
|
||||
int selectResult;
|
||||
do {
|
||||
timeval zeroTime;
|
||||
selectResult = select(x11displayFd + 1, &fdSet, null, null, &zeroTime);
|
||||
timeval timeout;
|
||||
timeout.tv_usec = msecs;
|
||||
selectResult = select(x11displayFd + 1, &fdSet, null, null, &timeout);
|
||||
} while(selectResult == -1 && errno == EINTR);
|
||||
if (selectResult < 0) {
|
||||
Log.e("X11: display fd select error");
|
||||
} else if (selectResult == 1) {
|
||||
Log.d("X11: XPending");
|
||||
//Log.d("X11: XPending");
|
||||
eventsInQueue = XPending(x11display);
|
||||
}
|
||||
}
|
||||
|
@ -1482,7 +1513,11 @@ class X11Platform : Platform {
|
|||
Log.d("X11: ButtonPress event");
|
||||
X11Window w = findWindow(event.xbutton.window);
|
||||
if (w) {
|
||||
w.processMouseEvent(MouseAction.ButtonDown, event.xbutton.button, event.xbutton.state, event.xbutton.x, event.xbutton.y);
|
||||
if (event.xbutton.button == 4 || event.xbutton.button == 5) {
|
||||
w.processMouseEvent(MouseAction.Wheel, 0, 0, 0, event.xbutton.button == 4 ? 1 : -1);
|
||||
} else {
|
||||
w.processMouseEvent(MouseAction.ButtonDown, event.xbutton.button, event.xbutton.state, event.xbutton.x, event.xbutton.y);
|
||||
}
|
||||
} else {
|
||||
Log.e("Window not found");
|
||||
}
|
||||
|
@ -1508,7 +1543,9 @@ class X11Platform : Platform {
|
|||
case EnterNotify:
|
||||
Log.d("X11: EnterNotify event");
|
||||
X11Window w = findWindow(event.xcrossing.window);
|
||||
if (!w) {
|
||||
if (w) {
|
||||
w.processMouseEvent(MouseAction.Move, 0, event.xmotion.state, event.xcrossing.x, event.xcrossing.y);
|
||||
} else {
|
||||
Log.e("Window not found");
|
||||
}
|
||||
break;
|
||||
|
@ -1616,6 +1653,9 @@ class X11Platform : Platform {
|
|||
w.handlePostedEvent(cast(uint)event.xclient.data.l[0]);
|
||||
} else if (event.xclient.message_type == atom_DLANGUI_TIMER_EVENT) {
|
||||
w.handleTimer();
|
||||
} else if (event.xclient.message_type == atom_DLANGUI_REDRAW_EVENT) {
|
||||
if (event.xclient.data.l[0] == w._lastRedrawEventCode)
|
||||
w.redraw();
|
||||
} else if (event.xclient.message_type == atom_WM_PROTOCOLS) {
|
||||
Log.d("Handling WM_PROTOCOLS");
|
||||
if ((event.xclient.format == 32) && (event.xclient.data.l[0]) == atom_WM_DELETE_WINDOW) {
|
||||
|
@ -1636,41 +1676,30 @@ class X11Platform : Platform {
|
|||
}
|
||||
}
|
||||
|
||||
protected void pumpEvents()
|
||||
{
|
||||
XFlush(x11display);
|
||||
// Note: only events we set the mask for are detected!
|
||||
while(numberOfPendingEvents())
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
XEvent event; /* the XEvent declaration !!! */
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts application message loop.
|
||||
*
|
||||
* When returned from this method, application is shutting down.
|
||||
*/
|
||||
override int enterMessageLoop() {
|
||||
import core.thread;
|
||||
XEvent event; /* the XEvent declaration !!! */
|
||||
KeySym key; /* a dealie-bob to handle KeyPress Events */
|
||||
char[255] text; /* a char buffer for KeyPress Events */
|
||||
|
||||
Log.d("enterMessageLoop()");
|
||||
|
||||
while(!allWindowsClosed()) {
|
||||
// Note: only events we set the mask for are detected!
|
||||
foreach(win; _windowMap) {
|
||||
if (win._needRedraw) {
|
||||
win.redraw();
|
||||
}
|
||||
}
|
||||
XFlush(x11display);
|
||||
int eventsInQueue = numberOfPendingEvents();
|
||||
if (!eventsInQueue) {
|
||||
debug(x11) Log.d("X11: Sleeping");
|
||||
Thread.sleep(dur!("msecs")(10));
|
||||
}
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
if (!numberOfPendingEvents())
|
||||
break;
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
pumpEvents();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1710,18 +1739,7 @@ class X11Platform : Platform {
|
|||
Log.e("Waiting for clipboard contents timeout");
|
||||
return ""d;
|
||||
}
|
||||
XFlush(x11display);
|
||||
int eventsInQueue = numberOfPendingEvents();
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
if (!numberOfPendingEvents())
|
||||
break;
|
||||
XEvent event;
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
pumpEvents();
|
||||
}
|
||||
Atom selectionTarget;
|
||||
int selectionFormat;
|
||||
|
@ -1780,15 +1798,9 @@ class X11Platform : Platform {
|
|||
|
||||
/// returns true if there is some modal window opened above this window, and this window should not process mouse/key input and should not allow closing
|
||||
override bool hasModalWindowsAbove(DWindow w) {
|
||||
// override in platform specific class
|
||||
for (uint i = 0; i + 1 < _windowList.length; i++) {
|
||||
if (_windowList[i] is w) {
|
||||
for (uint j = i + 1; j < _windowList.length; j++) {
|
||||
if (_windowList[j].flags & WindowFlag.Modal && _windowList[j].windowState != WindowState.hidden)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
X11Window x11Win = cast (X11Window) w;
|
||||
if (x11Win) {
|
||||
return x11Win.hasVisibleModalChild();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue