drop tab onto container

This commit is contained in:
nakst 2021-09-10 18:50:12 +01:00
parent 9ce99cde84
commit d96b07e115
7 changed files with 91 additions and 38 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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) {