mirror of https://gitlab.com/nakst/essence
drop tab onto container
This commit is contained in:
parent
9ce99cde84
commit
d96b07e115
|
@ -780,16 +780,21 @@ void EsInstanceDestroy(EsInstance *instance) {
|
||||||
EsElementDestroy(instance->window);
|
EsElementDestroy(instance->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
EsInstance *InstanceFromWindowID(uint64_t id) {
|
EsWindow *WindowFromWindowID(EsObjectID id) {
|
||||||
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
|
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
|
||||||
if (EsSyscall(ES_SYSCALL_WINDOW_GET_ID, gui.allWindows[i]->handle, 0, 0, 0) == id) {
|
if (gui.allWindows[i]->id == id) {
|
||||||
return gui.allWindows[i]->instance;
|
return gui.allWindows[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EsInstance *InstanceFromWindowID(EsObjectID id) {
|
||||||
|
EsWindow *window = WindowFromWindowID(id);
|
||||||
|
return window ? window->instance : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
EsError GetMessage(_EsMessageWithObject *message) {
|
EsError GetMessage(_EsMessageWithObject *message) {
|
||||||
// Process posted messages first,
|
// Process posted messages first,
|
||||||
// so that messages like ES_MSG_WINDOW_DESTROYED are received last.
|
// so that messages like ES_MSG_WINDOW_DESTROYED are received last.
|
||||||
|
|
|
@ -464,9 +464,9 @@ void WindowTabDestroy(WindowTab *tab) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowTab *WindowTabMoveToNewContainer(WindowTab *tab) {
|
WindowTab *WindowTabMoveToNewContainer(WindowTab *tab, ContainerWindow *container = nullptr) {
|
||||||
// Create the new tab and container window.
|
// Create the new tab and container window.
|
||||||
WindowTab *newTab = WindowTabCreate(ContainerWindowCreate());
|
WindowTab *newTab = WindowTabCreate(container ?: ContainerWindowCreate());
|
||||||
if (!newTab) return nullptr;
|
if (!newTab) return nullptr;
|
||||||
|
|
||||||
// Move ownership of the instance to the new tab.
|
// Move ownership of the instance to the new tab.
|
||||||
|
@ -480,6 +480,10 @@ WindowTab *WindowTabMoveToNewContainer(WindowTab *tab) {
|
||||||
// Destroy the old tab, and activate the new one.
|
// Destroy the old tab, and activate the new one.
|
||||||
WindowTabDestroy(tab); // Deplaces the embedded window from the old container.
|
WindowTabDestroy(tab); // Deplaces the embedded window from the old container.
|
||||||
WindowTabActivate(newTab);
|
WindowTabActivate(newTab);
|
||||||
|
|
||||||
|
// If this is an existing container window, make sure it's activated.
|
||||||
|
if (container) EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, newTab->window->handle, 0, 0, ES_WINDOW_PROPERTY_FOCUSED);
|
||||||
|
|
||||||
return newTab;
|
return newTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,9 +591,39 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
||||||
EsElementSetDisabled(band->GetChild(0), true);
|
EsElementSetDisabled(band->GetChild(0), true);
|
||||||
|
|
||||||
if (band->items.Length() == 1) {
|
if (band->items.Length() == 1) {
|
||||||
// TODO Dragging into other containers.
|
// Get the window we're hovering the tab over.
|
||||||
EsPoint screenPosition = EsMouseGetPosition();
|
EsObjectID hoverWindowID;
|
||||||
WindowChangeBounds(RESIZE_MOVE, screenPosition.x, screenPosition.y, &gui.lastClickX, &gui.lastClickY, band->window);
|
EsPoint mousePositionOnScreen = EsMouseGetPosition();
|
||||||
|
EsSyscall(ES_SYSCALL_WINDOW_FIND_BY_POINT, (uintptr_t) &hoverWindowID, mousePositionOnScreen.x, mousePositionOnScreen.y, tab->window->id);
|
||||||
|
EsWindow *hoverWindow = WindowFromWindowID(hoverWindowID);
|
||||||
|
bool dragInto = false;
|
||||||
|
|
||||||
|
if (hoverWindow && hoverWindow->windowStyle == ES_WINDOW_CONTAINER) {
|
||||||
|
// Are we hovering over the tab band?
|
||||||
|
ContainerWindow *hoverContainer = (ContainerWindow *) hoverWindow->userData.p;
|
||||||
|
EsRectangle hoverTabBandBounds = hoverContainer->tabBand->GetScreenBounds();
|
||||||
|
dragInto = EsRectangleContains(hoverTabBandBounds, mousePositionOnScreen.x, mousePositionOnScreen.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dragInto) {
|
||||||
|
// Move the current window.
|
||||||
|
WindowChangeBounds(RESIZE_MOVE, mousePositionOnScreen.x, mousePositionOnScreen.y, &gui.lastClickX, &gui.lastClickY, band->window);
|
||||||
|
} else {
|
||||||
|
ContainerWindow *hoverContainer = (ContainerWindow *) hoverWindow->userData.p;
|
||||||
|
int32_t dragOffset = mousePositionOnScreen.x - tab->GetScreenBounds().l;
|
||||||
|
|
||||||
|
// Move the tab into the new container.
|
||||||
|
EsSyscall(ES_SYSCALL_WINDOW_TRANSFER_PRESS, tab->window->handle, hoverWindow->handle, 0, 0);
|
||||||
|
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->window->handle, 0, 0, ES_WINDOW_PROPERTY_EMBED);
|
||||||
|
WindowTab *newTab = WindowTabMoveToNewContainer(tab, hoverContainer);
|
||||||
|
|
||||||
|
// Setup the drag in the new container.
|
||||||
|
// TODO Sometimes the tab ends up a few pixels off?
|
||||||
|
newTab->window->pressed = newTab;
|
||||||
|
newTab->window->dragged = newTab;
|
||||||
|
newTab->dragOffset = dragOffset + hoverContainer->tabBand->currentStyle->insets.l;
|
||||||
|
newTab->dragging = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
EsPoint mousePosition = EsMouseGetPosition(tab->window);
|
EsPoint mousePosition = EsMouseGetPosition(tab->window);
|
||||||
int32_t dragOffThreshold = GetConstantNumber("tabDragOffThreshold");
|
int32_t dragOffThreshold = GetConstantNumber("tabDragOffThreshold");
|
||||||
|
@ -598,6 +632,8 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
||||||
if (EsRectangleContains(EsRectangleAdd(band->GetWindowBounds(), ES_RECT_1I(-dragOffThreshold)), mousePosition.x, mousePosition.y)) {
|
if (EsRectangleContains(EsRectangleAdd(band->GetWindowBounds(), ES_RECT_1I(-dragOffThreshold)), mousePosition.x, mousePosition.y)) {
|
||||||
ReorderItemDragged(tab, message->mouseDragged.newPositionX);
|
ReorderItemDragged(tab, message->mouseDragged.newPositionX);
|
||||||
} else {
|
} else {
|
||||||
|
// TODO Moving a tab directly from one container to another.
|
||||||
|
|
||||||
// If we dragged the tab off the left or right side of the band, put it at the start of the new tab band.
|
// If we dragged the tab off the left or right side of the band, put it at the start of the new tab band.
|
||||||
bool putAtStart = tab->dragPosition < band->currentStyle->insets.l
|
bool putAtStart = tab->dragPosition < band->currentStyle->insets.l
|
||||||
|| tab->dragPosition + tab->width > band->width - band->currentStyle->insets.r;
|
|| tab->dragPosition + tab->width > band->width - band->currentStyle->insets.r;
|
||||||
|
@ -620,7 +656,10 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
||||||
gui.lastClickX = putAtStart ? putAtStartClickX : mousePosition.x;
|
gui.lastClickX = putAtStart ? putAtStartClickX : mousePosition.x;
|
||||||
gui.mouseButtonDown = true;
|
gui.mouseButtonDown = true;
|
||||||
gui.draggingStarted = true;
|
gui.draggingStarted = true;
|
||||||
WindowTabMessage(newTab, message);
|
|
||||||
|
// Update the bounds of the new container.
|
||||||
|
EsPoint mousePositionOnScreen = EsMouseGetPosition();
|
||||||
|
WindowChangeBounds(RESIZE_MOVE, mousePositionOnScreen.x, mousePositionOnScreen.y, &gui.lastClickX, &gui.lastClickY, newTab->window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -975,12 +1014,10 @@ void ShutdownModalCreate() {
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) {
|
void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) {
|
||||||
EsObjectID windowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||||
|
|
||||||
if (instance->tab && instance->tab->notRespondingInstance && instance->tab->notRespondingInstance->embeddedWindowID == windowID) {
|
if (instance->tab && instance->tab->notRespondingInstance && instance->tab->notRespondingInstance->embeddedWindowID == element->window->id) {
|
||||||
EsProcessTerminate(instance->processHandle, 1);
|
EsProcessTerminate(instance->processHandle, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1032,8 +1069,7 @@ void InstanceBlankTabCreate(EsMessage *message) {
|
||||||
button->userData = application;
|
button->userData = application;
|
||||||
|
|
||||||
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
|
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
|
||||||
EsObjectID tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
|
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(element->window->id);
|
||||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID);
|
|
||||||
|
|
||||||
if (ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance)) {
|
if (ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance)) {
|
||||||
WindowTabActivate(instance->tab, true);
|
WindowTabActivate(instance->tab, true);
|
||||||
|
|
|
@ -420,6 +420,7 @@ void HeapDuplicate(void **pointer, size_t *outBytes, const void *data, size_t by
|
||||||
|
|
||||||
struct EsWindow : EsElement {
|
struct EsWindow : EsElement {
|
||||||
EsHandle handle;
|
EsHandle handle;
|
||||||
|
EsObjectID id;
|
||||||
EsWindowStyle windowStyle;
|
EsWindowStyle windowStyle;
|
||||||
uint32_t windowWidth, windowHeight;
|
uint32_t windowWidth, windowHeight;
|
||||||
|
|
||||||
|
@ -879,6 +880,7 @@ EsWindow *EsWindowCreate(EsInstance *instance, EsWindowStyle style) {
|
||||||
window->handle = EsSyscall(ES_SYSCALL_WINDOW_CREATE, style, 0, (uintptr_t) window, 0);
|
window->handle = EsSyscall(ES_SYSCALL_WINDOW_CREATE, style, 0, (uintptr_t) window, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window->id = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, window->handle, 0, 0, 0);
|
||||||
window->Initialise(nullptr, ES_CELL_FILL, ProcessRootMessage, nullptr);
|
window->Initialise(nullptr, ES_CELL_FILL, ProcessRootMessage, nullptr);
|
||||||
window->cName = "window";
|
window->cName = "window";
|
||||||
window->window = window;
|
window->window = window;
|
||||||
|
|
|
@ -808,6 +808,7 @@ enum EsSyscallType {
|
||||||
ES_SYSCALL_WINDOW_REDRAW
|
ES_SYSCALL_WINDOW_REDRAW
|
||||||
ES_SYSCALL_WINDOW_MOVE
|
ES_SYSCALL_WINDOW_MOVE
|
||||||
ES_SYSCALL_WINDOW_TRANSFER_PRESS
|
ES_SYSCALL_WINDOW_TRANSFER_PRESS
|
||||||
|
ES_SYSCALL_WINDOW_FIND_BY_POINT
|
||||||
ES_SYSCALL_WINDOW_GET_ID
|
ES_SYSCALL_WINDOW_GET_ID
|
||||||
ES_SYSCALL_WINDOW_GET_BOUNDS
|
ES_SYSCALL_WINDOW_GET_BOUNDS
|
||||||
ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD
|
ES_SYSCALL_WINDOW_GET_EMBED_KEYBOARD
|
||||||
|
|
|
@ -775,6 +775,8 @@ bool MMHandlePageFault(MMSpace *space, uintptr_t address, unsigned faultFlags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MMRegion *MMReserve(MMSpace *space, size_t bytes, unsigned flags, uintptr_t forcedAddress, bool generateGuardPages) {
|
MMRegion *MMReserve(MMSpace *space, size_t bytes, unsigned flags, uintptr_t forcedAddress, bool generateGuardPages) {
|
||||||
|
// TODO Handling EsHeapAllocate failures.
|
||||||
|
|
||||||
MMRegion *outputRegion = nullptr;
|
MMRegion *outputRegion = nullptr;
|
||||||
size_t pagesNeeded = ((bytes + K_PAGE_SIZE - 1) & ~(K_PAGE_SIZE - 1)) / K_PAGE_SIZE;
|
size_t pagesNeeded = ((bytes + K_PAGE_SIZE - 1) & ~(K_PAGE_SIZE - 1)) / K_PAGE_SIZE;
|
||||||
|
|
||||||
|
|
|
@ -1144,6 +1144,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_TRANSFER_PRESS) {
|
||||||
|
|
||||||
if (windowManager.pressedWindow == oldWindow) {
|
if (windowManager.pressedWindow == oldWindow) {
|
||||||
windowManager.pressedWindow = newWindow;
|
windowManager.pressedWindow = newWindow;
|
||||||
|
newWindow->hoveringOverEmbed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KMutexRelease(&windowManager.mutex);
|
KMutexRelease(&windowManager.mutex);
|
||||||
|
@ -1151,6 +1152,16 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_TRANSFER_PRESS) {
|
||||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_FIND_BY_POINT) {
|
||||||
|
SYSCALL_PERMISSION(ES_PERMISSION_SCREEN_MODIFY);
|
||||||
|
KMutexAcquire(&windowManager.mutex);
|
||||||
|
Window *window = windowManager.FindWindowAtPosition(argument1 /* x */, argument2 /* y */, argument3 /* exclude */);
|
||||||
|
EsObjectID id = window ? window->id : 0;
|
||||||
|
KMutexRelease(&windowManager.mutex);
|
||||||
|
SYSCALL_WRITE(argument0, &id, sizeof(id));
|
||||||
|
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||||
|
}
|
||||||
|
|
||||||
SYSCALL_IMPLEMENT(ES_SYSCALL_CURSOR_POSITION_GET) {
|
SYSCALL_IMPLEMENT(ES_SYSCALL_CURSOR_POSITION_GET) {
|
||||||
EsPoint point = ES_POINT(windowManager.cursorX, windowManager.cursorY);
|
EsPoint point = ES_POINT(windowManager.cursorX, windowManager.cursorY);
|
||||||
SYSCALL_WRITE(argument0, &point, sizeof(EsPoint));
|
SYSCALL_WRITE(argument0, &point, sizeof(EsPoint));
|
||||||
|
|
|
@ -61,13 +61,12 @@ struct Window {
|
||||||
struct WindowManager {
|
struct WindowManager {
|
||||||
void *CreateWindow(Process *process, void *apiWindow, EsWindowStyle style);
|
void *CreateWindow(Process *process, void *apiWindow, EsWindowStyle style);
|
||||||
void *CreateEmbeddedWindow(Process *process, void *apiWindow);
|
void *CreateEmbeddedWindow(Process *process, void *apiWindow);
|
||||||
Window *FindWindowAtPosition(int cursorX, int cursorY);
|
Window *FindWindowAtPosition(int cursorX, int cursorY, EsObjectID exclude = 0);
|
||||||
|
|
||||||
void Initialise();
|
void Initialise();
|
||||||
|
|
||||||
void MoveCursor(int64_t xMovement, int64_t yMovement);
|
void MoveCursor(int64_t xMovement, int64_t yMovement);
|
||||||
void ClickCursor(unsigned buttons);
|
void ClickCursor(unsigned buttons);
|
||||||
void UpdateCursor(int xMovement, int yMovement, unsigned buttons);
|
|
||||||
void PressKey(unsigned scancode);
|
void PressKey(unsigned scancode);
|
||||||
|
|
||||||
void Redraw(EsPoint position, int width, int height, Window *except = nullptr, int startingAt = 0, bool addToModifiedRegion = true);
|
void Redraw(EsPoint position, int width, int height, Window *except = nullptr, int startingAt = 0, bool addToModifiedRegion = true);
|
||||||
|
@ -239,14 +238,15 @@ void SendMessageToWindow(Window *window, EsMessage *message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Window *WindowManager::FindWindowAtPosition(int cursorX, int cursorY) {
|
Window *WindowManager::FindWindowAtPosition(int cursorX, int cursorY, EsObjectID exclude) {
|
||||||
KMutexAssertLocked(&mutex);
|
KMutexAssertLocked(&mutex);
|
||||||
|
|
||||||
for (intptr_t i = windows.Length() - 1; i >= 0; i--) {
|
for (intptr_t i = windows.Length() - 1; i >= 0; i--) {
|
||||||
Window *window = windows[i];
|
Window *window = windows[i];
|
||||||
EsRectangle bounds = ES_RECT_4PD(window->position.x, window->position.y, window->width, window->height);
|
EsRectangle bounds = ES_RECT_4PD(window->position.x, window->position.y, window->width, window->height);
|
||||||
|
|
||||||
if (window->solid && !window->hidden && EsRectangleContains(EsRectangleAdd(bounds, window->solidInsets), cursorX, cursorY)
|
if (window->solid && !window->hidden && exclude != window->id
|
||||||
|
&& EsRectangleContains(EsRectangleAdd(bounds, window->solidInsets), cursorX, cursorY)
|
||||||
&& (!window->isMaximised || EsRectangleContains(workArea, cursorX, cursorY))) {
|
&& (!window->isMaximised || EsRectangleContains(workArea, cursorX, cursorY))) {
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
@ -255,24 +255,6 @@ Window *WindowManager::FindWindowAtPosition(int cursorX, int cursorY) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::UpdateCursor(int xMovement, int yMovement, unsigned buttons) {
|
|
||||||
if (!initialised) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xMovement || yMovement) {
|
|
||||||
if (xMovement * xMovement + yMovement * yMovement < 10 && buttons != lastButtons) {
|
|
||||||
// This seems to be movement noise generated when the buttons were pressed/released.
|
|
||||||
} else {
|
|
||||||
KMutexAcquire(&mutex);
|
|
||||||
MoveCursor(xMovement, yMovement);
|
|
||||||
KMutexRelease(&mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClickCursor(buttons);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::EndEyedrop(bool cancelled) {
|
void WindowManager::EndEyedrop(bool cancelled) {
|
||||||
KMutexAssertLocked(&mutex);
|
KMutexAssertLocked(&mutex);
|
||||||
|
|
||||||
|
@ -1222,7 +1204,21 @@ void WindowManager::StartEyedrop(uintptr_t object, Window *avoid, uint32_t cance
|
||||||
}
|
}
|
||||||
|
|
||||||
void KCursorUpdate(int xMovement, int yMovement, unsigned buttons) {
|
void KCursorUpdate(int xMovement, int yMovement, unsigned buttons) {
|
||||||
windowManager.UpdateCursor(xMovement, yMovement, buttons);
|
if (!windowManager.initialised) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xMovement || yMovement) {
|
||||||
|
if (xMovement * xMovement + yMovement * yMovement < 10 && buttons != windowManager.lastButtons) {
|
||||||
|
// This seems to be movement noise generated when the buttons were pressed/released.
|
||||||
|
} else {
|
||||||
|
KMutexAcquire(&windowManager.mutex);
|
||||||
|
windowManager.MoveCursor(xMovement, yMovement);
|
||||||
|
KMutexRelease(&windowManager.mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
windowManager.ClickCursor(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KKeyPress(unsigned scancode) {
|
void KKeyPress(unsigned scancode) {
|
||||||
|
|
Loading…
Reference in New Issue