mirror of https://gitlab.com/nakst/essence
drag off tabs
This commit is contained in:
parent
fa613d62d7
commit
eb18fd7e21
|
@ -464,9 +464,10 @@ void WindowTabDestroy(WindowTab *tab) {
|
|||
}
|
||||
}
|
||||
|
||||
void WindowTabMoveToNewContainer(WindowTab *tab) {
|
||||
WindowTab *WindowTabMoveToNewContainer(WindowTab *tab) {
|
||||
// Create the new tab and container window.
|
||||
WindowTab *newTab = WindowTabCreate(ContainerWindowCreate());
|
||||
if (!newTab) return nullptr;
|
||||
|
||||
// Move ownership of the instance to the new tab.
|
||||
newTab->applicationInstance = tab->applicationInstance;
|
||||
|
@ -479,6 +480,7 @@ void WindowTabMoveToNewContainer(WindowTab *tab) {
|
|||
// Destroy the old tab, and activate the new one.
|
||||
WindowTabDestroy(tab); // Deplaces the embedded window from the old container.
|
||||
WindowTabActivate(newTab);
|
||||
return newTab;
|
||||
}
|
||||
|
||||
int ContainerWindowMessage(EsElement *element, EsMessage *message) {
|
||||
|
@ -582,14 +584,59 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
|||
message->animate.complete = ReorderItemAnimate(tab, message->animate.deltaMs, "windowTabEntranceDuration");
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) {
|
||||
EsElementSetDisabled(band->GetChild(0), true);
|
||||
|
||||
if (band->items.Length() == 1) {
|
||||
// TODO Dragging into other containers.
|
||||
EsPoint screenPosition = EsMouseGetPosition();
|
||||
WindowChangeBounds(RESIZE_MOVE, screenPosition.x, screenPosition.y, &gui.lastClickX, &gui.lastClickY, band->window);
|
||||
} else {
|
||||
ReorderItemDragged(tab, message->mouseDragged.newPositionX);
|
||||
}
|
||||
EsRectangle tabBarBounds = tab->parent->GetWindowBounds();
|
||||
EsRectangle tabBounds = tab->GetWindowBounds();
|
||||
int32_t mouseX = message->mouseDragged.newPositionX + tabBounds.l;
|
||||
int32_t mouseY = message->mouseDragged.newPositionY + tabBounds.t;
|
||||
int32_t dragOffThreshold = GetConstantNumber("tabDragOffThreshold");
|
||||
|
||||
EsElementSetDisabled(band->GetChild(0), true);
|
||||
if (EsRectangleContains(EsRectangleAdd(tabBarBounds, ES_RECT_1I(-dragOffThreshold)), mouseX, mouseY)) {
|
||||
ReorderItemDragged(tab, message->mouseDragged.newPositionX);
|
||||
} else {
|
||||
// Save information about the old container.
|
||||
int32_t oldTabDragX = mouseX - tab->dragOffset;
|
||||
int32_t oldTabDragY = mouseY - (gui.lastClickY - tab->offsetY);
|
||||
EsRectangle oldContainerBounds = tab->window->GetScreenBounds();
|
||||
EsRectangle oldTabBarScreenBounds = tab->parent->GetScreenBounds();
|
||||
EsWindow *oldContainer = tab->window;
|
||||
EsPoint mousePosition = EsMouseGetPosition(oldContainer);
|
||||
|
||||
// End the drag on this container.
|
||||
EsMessage m = { .type = ES_MSG_MOUSE_LEFT_UP };
|
||||
UIMouseUp(oldContainer, &m, false);
|
||||
|
||||
// Move the tab to a new container.
|
||||
WindowTab *newTab = WindowTabMoveToNewContainer(tab);
|
||||
|
||||
if (newTab) {
|
||||
// Work out the position of the new container, so that the mouse position within the tab is preserved.
|
||||
newTab->window->width = Width(oldContainerBounds);
|
||||
newTab->window->height = Height(oldContainerBounds);
|
||||
UIWindowLayoutNow(newTab->window, nullptr);
|
||||
EsRectangle newTabWindowBounds = newTab->GetWindowBounds();
|
||||
EsRectangle bounds = ES_RECT_4PD(oldTabBarScreenBounds.l + oldTabDragX - newTabWindowBounds.l,
|
||||
oldTabBarScreenBounds.t + oldTabDragY - newTabWindowBounds.t,
|
||||
Width(oldContainerBounds), Height(oldContainerBounds));
|
||||
EsSyscall(ES_SYSCALL_WINDOW_MOVE, newTab->window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_DYNAMIC);
|
||||
|
||||
// Start the drag on the new container.
|
||||
EsSyscall(ES_SYSCALL_WINDOW_TRANSFER_PRESS, oldContainer->handle, newTab->window->handle, 0, 0);
|
||||
newTab->window->pressed = newTab;
|
||||
newTab->window->dragged = newTab;
|
||||
gui.mouseButtonDown = true;
|
||||
gui.draggingStarted = true;
|
||||
gui.lastClickX = mousePosition.x + oldContainerBounds.l - bounds.l;
|
||||
gui.lastClickY = mousePosition.y + oldContainerBounds.t - bounds.t;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_UP) {
|
||||
ReorderItemDragComplete(tab);
|
||||
EsElementSetDisabled(band->GetChild(0), false);
|
||||
|
|
127
desktop/gui.cpp
127
desktop/gui.cpp
|
@ -79,7 +79,7 @@ EsElement *WindowGetMainPanel(EsWindow *window);
|
|||
int AccessKeyLayerMessage(EsElement *element, EsMessage *message);
|
||||
void AccessKeyModeExit();
|
||||
int ProcessButtonMessage(EsElement *element, EsMessage *message);
|
||||
void UIMousePressReleased(EsWindow *window, EsMessage *message, bool sendClick);
|
||||
void UIMouseUp(EsWindow *window, EsMessage *message, bool sendClick);
|
||||
void UIMaybeRemoveFocusedElement(EsWindow *window);
|
||||
EsTextStyle TextPlanGetPrimaryStyle(EsTextPlan *plan);
|
||||
EsElement *UIFindHoverElementRecursively(EsElement *element, int offsetX, int offsetY, EsPoint position);
|
||||
|
@ -860,7 +860,7 @@ EsWindow *EsWindowCreate(EsInstance *instance, EsWindowStyle style) {
|
|||
EsMessageMutexCheck();
|
||||
|
||||
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
|
||||
UIMousePressReleased(gui.allWindows[i], nullptr, false);
|
||||
UIMouseUp(gui.allWindows[i], nullptr, false);
|
||||
}
|
||||
|
||||
EsWindow *window = (EsWindow *) EsHeapAllocate(sizeof(EsWindow), true);
|
||||
|
@ -6063,7 +6063,67 @@ int UIMessageSendPropagateToAncestors(EsElement *element, EsMessage *message, Es
|
|||
return 0;
|
||||
}
|
||||
|
||||
void UIMousePressReleased(EsWindow *window, EsMessage *message, bool sendClick) {
|
||||
void UIMouseDown(EsWindow *window, EsMessage *message) {
|
||||
window->mousePosition.x = message->mouseDown.positionX;
|
||||
window->mousePosition.y = message->mouseDown.positionY;
|
||||
|
||||
AccessKeyModeExit();
|
||||
|
||||
double timeStampMs = EsTimeStampMs();
|
||||
|
||||
if (gui.clickChainStartMs + api.global->clickChainTimeoutMs < timeStampMs
|
||||
|| window->hovered != gui.clickChainElement) {
|
||||
// Start a new click chain.
|
||||
gui.clickChainStartMs = timeStampMs;
|
||||
gui.clickChainCount = 1;
|
||||
gui.clickChainElement = window->hovered;
|
||||
} else {
|
||||
gui.clickChainStartMs = timeStampMs;
|
||||
gui.clickChainCount++;
|
||||
}
|
||||
|
||||
message->mouseDown.clickChainCount = gui.clickChainCount;
|
||||
|
||||
gui.lastClickX = message->mouseDown.positionX;
|
||||
gui.lastClickY = message->mouseDown.positionY;
|
||||
gui.lastClickButton = message->type;
|
||||
gui.mouseButtonDown = true;
|
||||
|
||||
if ((~window->hovered->flags & ES_ELEMENT_DISABLED) && (~window->hovered->state & UI_STATE_BLOCK_INTERACTION)) {
|
||||
// If the hovered element is destroyed in response to one of these messages,
|
||||
// window->hovered will be set to nullptr, so save the element here.
|
||||
EsElement *element = window->hovered;
|
||||
|
||||
if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||
element->state |= UI_STATE_LEFT_PRESSED;
|
||||
}
|
||||
|
||||
window->pressed = element;
|
||||
EsMessage m = { ES_MSG_PRESSED_START };
|
||||
EsMessageSend(element, &m);
|
||||
|
||||
EsRectangle bounds = element->GetWindowBounds();
|
||||
message->mouseDown.positionX -= bounds.l;
|
||||
message->mouseDown.positionY -= bounds.t;
|
||||
|
||||
if (ES_REJECTED != UIMessageSendPropagateToAncestors(element, message, &window->dragged)) {
|
||||
if (window->dragged && (~window->dragged->flags & ES_ELEMENT_NO_FOCUS_ON_CLICK)) {
|
||||
EsElementFocus(window->dragged, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (window->hovered != window->focused && window->focused && (~window->focused->state & UI_STATE_LOST_STRONG_FOCUS)) {
|
||||
EsMessage m = { ES_MSG_STRONG_FOCUS_END };
|
||||
window->focused->state |= UI_STATE_LOST_STRONG_FOCUS;
|
||||
EsMessageSend(window->focused, &m);
|
||||
}
|
||||
}
|
||||
|
||||
void UIMouseUp(EsWindow *window, EsMessage *message, bool sendClick) {
|
||||
gui.mouseButtonDown = false;
|
||||
window->dragged = nullptr;
|
||||
|
||||
if (window->pressed) {
|
||||
EsElement *pressed = window->pressed;
|
||||
window->pressed = nullptr;
|
||||
|
@ -6447,7 +6507,7 @@ void UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
|
|||
|
||||
if (window->pressed) {
|
||||
if (message->keyboard.scancode == ES_SCANCODE_ESCAPE) {
|
||||
UIMousePressReleased(window, nullptr, false);
|
||||
UIMouseUp(window, nullptr, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -6787,71 +6847,16 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process
|
|||
} else if (message->type == ES_MSG_MOUSE_EXIT) {
|
||||
window->hovering = false;
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN || message->type == ES_MSG_MOUSE_RIGHT_DOWN || message->type == ES_MSG_MOUSE_MIDDLE_DOWN) {
|
||||
window->mousePosition.x = message->mouseDown.positionX;
|
||||
window->mousePosition.y = message->mouseDown.positionY;
|
||||
|
||||
AccessKeyModeExit();
|
||||
|
||||
if (gui.mouseButtonDown || window->targetMenu) {
|
||||
goto skipInputMessage;
|
||||
}
|
||||
|
||||
double timeStampMs = EsTimeStampMs();
|
||||
|
||||
if (gui.clickChainStartMs + api.global->clickChainTimeoutMs < timeStampMs
|
||||
|| window->hovered != gui.clickChainElement) {
|
||||
// Start a new click chain.
|
||||
gui.clickChainStartMs = timeStampMs;
|
||||
gui.clickChainCount = 1;
|
||||
gui.clickChainElement = window->hovered;
|
||||
} else {
|
||||
gui.clickChainStartMs = timeStampMs;
|
||||
gui.clickChainCount++;
|
||||
}
|
||||
|
||||
message->mouseDown.clickChainCount = gui.clickChainCount;
|
||||
|
||||
gui.lastClickX = message->mouseDown.positionX;
|
||||
gui.lastClickY = message->mouseDown.positionY;
|
||||
gui.lastClickButton = message->type;
|
||||
gui.mouseButtonDown = true;
|
||||
|
||||
if ((~window->hovered->flags & ES_ELEMENT_DISABLED) && (~window->hovered->state & UI_STATE_BLOCK_INTERACTION)) {
|
||||
// If the hovered element is destroyed in response to one of these messages,
|
||||
// window->hovered will be set to nullptr, so save the element here.
|
||||
EsElement *element = window->hovered;
|
||||
|
||||
if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||
element->state |= UI_STATE_LEFT_PRESSED;
|
||||
}
|
||||
|
||||
window->pressed = element;
|
||||
EsMessage m = { ES_MSG_PRESSED_START };
|
||||
EsMessageSend(element, &m);
|
||||
|
||||
EsRectangle bounds = element->GetWindowBounds();
|
||||
message->mouseDown.positionX -= bounds.l;
|
||||
message->mouseDown.positionY -= bounds.t;
|
||||
|
||||
if (ES_REJECTED != UIMessageSendPropagateToAncestors(element, message, &window->dragged)) {
|
||||
if (window->dragged && (~window->dragged->flags & ES_ELEMENT_NO_FOCUS_ON_CLICK)) {
|
||||
EsElementFocus(window->dragged, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (window->hovered != window->focused && window->focused && (~window->focused->state & UI_STATE_LOST_STRONG_FOCUS)) {
|
||||
EsMessage m = { ES_MSG_STRONG_FOCUS_END };
|
||||
window->focused->state |= UI_STATE_LOST_STRONG_FOCUS;
|
||||
EsMessageSend(window->focused, &m);
|
||||
}
|
||||
UIMouseDown(window, message);
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_UP || message->type == ES_MSG_MOUSE_RIGHT_UP || message->type == ES_MSG_MOUSE_MIDDLE_UP) {
|
||||
AccessKeyModeExit();
|
||||
|
||||
if (gui.mouseButtonDown && gui.lastClickButton == message->type - 1) {
|
||||
gui.mouseButtonDown = false;
|
||||
window->dragged = nullptr;
|
||||
UIMousePressReleased(window, message, true);
|
||||
UIMouseUp(window, message, true);
|
||||
}
|
||||
} else if (message->type == ES_MSG_KEY_UP || message->type == ES_MSG_KEY_DOWN) {
|
||||
UIHandleKeyMessage(window, message);
|
||||
|
|
|
@ -807,6 +807,7 @@ enum EsSyscallType {
|
|||
ES_SYSCALL_WINDOW_CLOSE
|
||||
ES_SYSCALL_WINDOW_REDRAW
|
||||
ES_SYSCALL_WINDOW_MOVE
|
||||
ES_SYSCALL_WINDOW_TRANSFER_PRESS
|
||||
ES_SYSCALL_WINDOW_GET_ID
|
||||
ES_SYSCALL_WINDOW_GET_BOUNDS
|
||||
ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD
|
||||
|
|
|
@ -1132,6 +1132,25 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_MOVE) {
|
|||
SYSCALL_RETURN(success ? ES_SUCCESS : ES_ERROR_INVALID_DIMENSIONS, false);
|
||||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_TRANSFER_PRESS) {
|
||||
KObject _oldWindow(currentProcess, argument0, KERNEL_OBJECT_WINDOW);
|
||||
CHECK_OBJECT(_oldWindow);
|
||||
Window *oldWindow = (Window *) _oldWindow.object;
|
||||
KObject _newWindow(currentProcess, argument1, KERNEL_OBJECT_WINDOW);
|
||||
CHECK_OBJECT(_newWindow);
|
||||
Window *newWindow = (Window *) _newWindow.object;
|
||||
|
||||
KMutexAcquire(&windowManager.mutex);
|
||||
|
||||
if (windowManager.pressedWindow == oldWindow) {
|
||||
windowManager.pressedWindow = newWindow;
|
||||
}
|
||||
|
||||
KMutexRelease(&windowManager.mutex);
|
||||
|
||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_CURSOR_POSITION_GET) {
|
||||
EsPoint point = ES_POINT(windowManager.cursorX, windowManager.cursorY);
|
||||
SYSCALL_WRITE(argument0, &point, sizeof(EsPoint));
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue