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);
|
||||
}
|
||||
|
||||
EsInstance *InstanceFromWindowID(uint64_t id) {
|
||||
EsWindow *WindowFromWindowID(EsObjectID id) {
|
||||
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) {
|
||||
return gui.allWindows[i]->instance;
|
||||
if (gui.allWindows[i]->id == id) {
|
||||
return gui.allWindows[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EsInstance *InstanceFromWindowID(EsObjectID id) {
|
||||
EsWindow *window = WindowFromWindowID(id);
|
||||
return window ? window->instance : nullptr;
|
||||
}
|
||||
|
||||
EsError GetMessage(_EsMessageWithObject *message) {
|
||||
// Process posted messages first,
|
||||
// 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.
|
||||
WindowTab *newTab = WindowTabCreate(ContainerWindowCreate());
|
||||
WindowTab *newTab = WindowTabCreate(container ?: ContainerWindowCreate());
|
||||
if (!newTab) return nullptr;
|
||||
|
||||
// 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.
|
||||
WindowTabDestroy(tab); // Deplaces the embedded window from the old container.
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -587,9 +591,39 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
|||
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);
|
||||
// Get the window we're hovering the tab over.
|
||||
EsObjectID hoverWindowID;
|
||||
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 {
|
||||
EsPoint mousePosition = EsMouseGetPosition(tab->window);
|
||||
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)) {
|
||||
ReorderItemDragged(tab, message->mouseDragged.newPositionX);
|
||||
} 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.
|
||||
bool putAtStart = tab->dragPosition < band->currentStyle->insets.l
|
||||
|| 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.mouseButtonDown = 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 *) {
|
||||
EsObjectID windowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); 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);
|
||||
break;
|
||||
}
|
||||
|
@ -1032,8 +1069,7 @@ void InstanceBlankTabCreate(EsMessage *message) {
|
|||
button->userData = application;
|
||||
|
||||
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
|
||||
EsObjectID tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
|
||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID);
|
||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(element->window->id);
|
||||
|
||||
if (ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance)) {
|
||||
WindowTabActivate(instance->tab, true);
|
||||
|
|
|
@ -420,6 +420,7 @@ void HeapDuplicate(void **pointer, size_t *outBytes, const void *data, size_t by
|
|||
|
||||
struct EsWindow : EsElement {
|
||||
EsHandle handle;
|
||||
EsObjectID id;
|
||||
EsWindowStyle windowStyle;
|
||||
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->id = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, window->handle, 0, 0, 0);
|
||||
window->Initialise(nullptr, ES_CELL_FILL, ProcessRootMessage, nullptr);
|
||||
window->cName = "window";
|
||||
window->window = window;
|
||||
|
|
|
@ -286,7 +286,7 @@ define ES_ERROR_FILE_ALREADY_EXISTS (-19)
|
|||
define ES_ERROR_FILE_DOES_NOT_EXIST (-20)
|
||||
define ES_ERROR_DRIVE_ERROR_FILE_DAMAGED (-21)
|
||||
define ES_ERROR_ACCESS_NOT_WITHIN_FILE_BOUNDS (-22)
|
||||
define ES_ERROR_PERMISSION_NOT_GRANTED (-23)
|
||||
define ES_ERROR_PERMISSION_NOT_GRANTED (-23)
|
||||
define ES_ERROR_FILE_IN_EXCLUSIVE_USE (-24)
|
||||
define ES_ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE (-25)
|
||||
define ES_ERROR_INCORRECT_NODE_TYPE (-26)
|
||||
|
@ -808,6 +808,7 @@ enum EsSyscallType {
|
|||
ES_SYSCALL_WINDOW_REDRAW
|
||||
ES_SYSCALL_WINDOW_MOVE
|
||||
ES_SYSCALL_WINDOW_TRANSFER_PRESS
|
||||
ES_SYSCALL_WINDOW_FIND_BY_POINT
|
||||
ES_SYSCALL_WINDOW_GET_ID
|
||||
ES_SYSCALL_WINDOW_GET_BOUNDS
|
||||
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) {
|
||||
// TODO Handling EsHeapAllocate failures.
|
||||
|
||||
MMRegion *outputRegion = nullptr;
|
||||
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) {
|
||||
windowManager.pressedWindow = newWindow;
|
||||
newWindow->hoveringOverEmbed = false;
|
||||
}
|
||||
|
||||
KMutexRelease(&windowManager.mutex);
|
||||
|
@ -1151,6 +1152,16 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_TRANSFER_PRESS) {
|
|||
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) {
|
||||
EsPoint point = ES_POINT(windowManager.cursorX, windowManager.cursorY);
|
||||
SYSCALL_WRITE(argument0, &point, sizeof(EsPoint));
|
||||
|
|
|
@ -61,13 +61,12 @@ struct Window {
|
|||
struct WindowManager {
|
||||
void *CreateWindow(Process *process, void *apiWindow, EsWindowStyle style);
|
||||
void *CreateEmbeddedWindow(Process *process, void *apiWindow);
|
||||
Window *FindWindowAtPosition(int cursorX, int cursorY);
|
||||
Window *FindWindowAtPosition(int cursorX, int cursorY, EsObjectID exclude = 0);
|
||||
|
||||
void Initialise();
|
||||
|
||||
void MoveCursor(int64_t xMovement, int64_t yMovement);
|
||||
void ClickCursor(unsigned buttons);
|
||||
void UpdateCursor(int xMovement, int yMovement, unsigned buttons);
|
||||
void PressKey(unsigned scancode);
|
||||
|
||||
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);
|
||||
|
||||
for (intptr_t i = windows.Length() - 1; i >= 0; i--) {
|
||||
Window *window = windows[i];
|
||||
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))) {
|
||||
return window;
|
||||
}
|
||||
|
@ -255,24 +255,6 @@ Window *WindowManager::FindWindowAtPosition(int cursorX, int cursorY) {
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue