From fa613d62d7598086832cb49840a8284f5b2d0db3 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Fri, 10 Sep 2021 10:38:50 +0100 Subject: [PATCH] move tab to new window menu --- apps/test.cpp | 1 + desktop/desktop.cpp | 76 ++++++++++++++++++++++++++++++------------- desktop/gui.cpp | 72 +++++++++++++++++++++++----------------- kernel/windows.cpp | 5 +++ res/Theme Source.dat | Bin 52202 -> 52257 bytes res/Themes/Theme.dat | Bin 53568 -> 53608 bytes shared/strings.cpp | 8 +++-- 7 files changed, 107 insertions(+), 55 deletions(-) diff --git a/apps/test.cpp b/apps/test.cpp index 100d9a8..9ac477b 100644 --- a/apps/test.cpp +++ b/apps/test.cpp @@ -154,6 +154,7 @@ void InitialiseInstance(EsInstance *instance) { EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Hang"), [] (EsInstance *, EsElement *, EsCommand *) { while (true); }); EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Wait"), [] (EsInstance *, EsElement *, EsCommand *) { EsSleep(8000); }); EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Wait, then crash"), [] (EsInstance *, EsElement *, EsCommand *) { EsSleep(8000); EsAssert(false); }); + EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Wait, then exit"), [] (EsInstance *, EsElement *, EsCommand *) { EsSleep(1000); EsProcessTerminateCurrent(); }); EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash 2"), [] (EsInstance *, EsElement *, EsCommand *) { EsSyscall(ES_SYSCALL_WAIT, 0x8000000000000000, 1, 0, 0); diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 03ebdcc..2b05875 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -63,6 +63,7 @@ struct ReorderList : EsElement { }; struct WindowTab : ReorderItem { + // NOTE Don't forget to update WindowTabMoveToNewContainer when modifying this. struct ContainerWindow *container; struct ApplicationInstance *applicationInstance; struct ApplicationInstance *notRespondingInstance; @@ -209,6 +210,8 @@ void ConfigurationWriteToFile(); void OpenDocumentOpenReference(EsObjectID id); void OpenDocumentCloseReference(EsObjectID id); void WallpaperLoad(EsGeneric); +WindowTab *WindowTabCreate(ContainerWindow *container); +ContainerWindow *ContainerWindowCreate(); #include "settings.cpp" @@ -439,6 +442,45 @@ void WindowTabActivate(WindowTab *tab, bool force = false) { } } +void WindowTabDestroy(WindowTab *tab) { + ContainerWindow *container = tab->container; + + if (container->tabBand->items.Length() == 1) { + EsElementDestroy(container->window); + EsElementDestroy(container->taskBarButton); + desktop.allContainerWindows.FindAndDeleteSwap(container, true); + } else { + if (container->active == tab) { + container->active = nullptr; + + for (uintptr_t i = 0; i < container->tabBand->items.Length(); i++) { + if (container->tabBand->items[i] != tab) continue; + WindowTabActivate((WindowTab *) container->tabBand->items[i ? (i - 1) : 1]); + break; + } + } + + EsElementDestroy(tab); + } +} + +void WindowTabMoveToNewContainer(WindowTab *tab) { + // Create the new tab and container window. + WindowTab *newTab = WindowTabCreate(ContainerWindowCreate()); + + // Move ownership of the instance to the new tab. + newTab->applicationInstance = tab->applicationInstance; + newTab->notRespondingInstance = tab->notRespondingInstance; + EsAssert(tab->applicationInstance->tab == tab); + tab->applicationInstance->tab = newTab; + tab->applicationInstance = nullptr; + tab->notRespondingInstance = nullptr; + + // Destroy the old tab, and activate the new one. + WindowTabDestroy(tab); // Deplaces the embedded window from the old container. + WindowTabActivate(newTab); +} + int ContainerWindowMessage(EsElement *element, EsMessage *message) { ContainerWindow *container = (ContainerWindow *) element->userData.p; @@ -558,6 +600,12 @@ int WindowTabMessage(EsElement *element, EsMessage *message) { WindowTabClose((WindowTab *) context.p); }, tab); + if (tab->container->tabBand->items.Length() > 1) { + EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopMoveTabToNewWindow), [] (EsMenu *, EsGeneric context) { + WindowTabMoveToNewContainer((WindowTab *) context.p); + }, tab); + } + if (EsKeyboardIsShiftHeld()) { EsMenuAddSeparator(menu); @@ -581,10 +629,9 @@ int WindowTabMessage(EsElement *element, EsMessage *message) { return ES_HANDLED; } -WindowTab *WindowTabCreate(ContainerWindow *container, ApplicationInstance *instance) { +WindowTab *WindowTabCreate(ContainerWindow *container) { WindowTab *tab = (WindowTab *) EsHeapAllocate(sizeof(WindowTab), true); tab->container = container; - tab->applicationInstance = instance; tab->Initialise(container->tabBand, ES_CELL_H_SHRINK | ES_CELL_V_BOTTOM, WindowTabMessage, nullptr); tab->cName = "window tab"; @@ -1196,7 +1243,8 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupInformation *startupInformation, ContainerWindow *container, bool hidden) { ApplicationInstance *instance = (ApplicationInstance *) EsHeapAllocate(sizeof(ApplicationInstance), true); - WindowTab *tab = !hidden ? WindowTabCreate(container ?: ContainerWindowCreate(), instance) : nullptr; + WindowTab *tab = !hidden ? WindowTabCreate(container ?: ContainerWindowCreate()) : nullptr; + if (tab) tab->applicationInstance = instance; instance->title[0] = ' '; instance->titleBytes = 1; instance->tab = tab; @@ -2227,7 +2275,7 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) { } void EmbeddedWindowDestroyed(EsObjectID id) { - EsMenuCloseAll(); + EsMenuCloseAll(); // The tab will be destroyed, but menus might be keeping pointers to it. ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */); if (!instance) return; @@ -2259,25 +2307,7 @@ void EmbeddedWindowDestroyed(EsObjectID id) { } if (instance->tab) { - ContainerWindow *container = instance->tab->container; - - if (container->tabBand->items.Length() == 1) { - EsElementDestroy(container->window); - EsElementDestroy(container->taskBarButton); - desktop.allContainerWindows.FindAndDeleteSwap(container, true); - } else { - if (container->active == instance->tab) { - container->active = nullptr; - - for (uintptr_t i = 0; i < container->tabBand->items.Length(); i++) { - if (container->tabBand->items[i] != instance->tab) continue; - WindowTabActivate((WindowTab *) container->tabBand->items[i ? (i - 1) : 1]); - break; - } - } - - EsElementDestroy(instance->tab); - } + WindowTabDestroy(instance->tab); } else if (instance->isUserTask) { desktop.totalUserTaskProgress -= instance->progress; EsElementRepaint(desktop.tasksButton); diff --git a/desktop/gui.cpp b/desktop/gui.cpp index 4dd0d68..40a6b6f 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -5289,6 +5289,16 @@ void EsElement::Destroy(bool manual) { } } + if (state & UI_STATE_MENU_SOURCE) { + for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) { + if (gui.allWindows[i]->source == this) { + // Close the menu attached to this element. + EsElementDestroy(gui.allWindows[i]); + break; + } + } + } + state |= UI_STATE_DESTROYING | UI_STATE_DESTROYING_CHILD | UI_STATE_BLOCK_INTERACTION; if (parent) { @@ -6935,42 +6945,46 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process window->mousePosition.x -= windowBounds.l, window->mousePosition.y -= windowBounds.t; window->hovering = true; } else if (message->type == ES_MSG_WINDOW_DEACTIVATED) { - AccessKeyModeExit(); + if (window->activated) { + AccessKeyModeExit(); - if (window->windowStyle == ES_WINDOW_MENU) { - window->Destroy(); + if (window->windowStyle == ES_WINDOW_MENU) { + window->Destroy(); + } + + window->activated = false; + window->hovering = false; + + if (window->focused) { + window->inactiveFocus = window->focused; + window->inactiveFocus->Repaint(true); + UIRemoveFocusFromElement(window->focused); + window->focused = nullptr; + } + + EsMessageSend(window, message); + UIMaybeRefreshStyleAll(window); } - - window->activated = false; - window->hovering = false; - - if (window->focused) { - window->inactiveFocus = window->focused; - window->inactiveFocus->Repaint(true); - UIRemoveFocusFromElement(window->focused); - window->focused = nullptr; - } - - EsMessageSend(window, message); - UIMaybeRefreshStyleAll(window); } else if (message->type == ES_MSG_WINDOW_ACTIVATED) { - AccessKeyModeExit(); + if (!window->activated) { + AccessKeyModeExit(); - gui.leftModifiers = gui.rightModifiers = 0; - gui.clickChainStartMs = 0; + gui.leftModifiers = gui.rightModifiers = 0; + gui.clickChainStartMs = 0; - window->activated = true; - EsMessage m = { ES_MSG_WINDOW_ACTIVATED }; - EsMessageSend(window, &m); + window->activated = true; + EsMessage m = { ES_MSG_WINDOW_ACTIVATED }; + EsMessageSend(window, &m); - if (!window->focused && window->inactiveFocus) { - EsElementFocus(window->inactiveFocus, false); - window->inactiveFocus->Repaint(true); - window->inactiveFocus = nullptr; + if (!window->focused && window->inactiveFocus) { + EsElementFocus(window->inactiveFocus, false); + window->inactiveFocus->Repaint(true); + window->inactiveFocus = nullptr; + } + + UIRefreshPrimaryClipboard(window); + UIMaybeRefreshStyleAll(window); } - - UIRefreshPrimaryClipboard(window); - UIMaybeRefreshStyleAll(window); } skipInputMessage:; diff --git a/kernel/windows.cpp b/kernel/windows.cpp index 92f0511..809aedf 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -1186,6 +1186,11 @@ void Window::SetEmbed(EmbeddedWindow *newEmbed) { if (embed) { embed->container = this; ResizeEmbed(); + + EsMessage message; + EsMemoryZero(&message, sizeof(message)); + message.type = windowManager.activeWindow == this ? ES_MSG_WINDOW_ACTIVATED : ES_MSG_WINDOW_DEACTIVATED; + embed->owner->messageQueue.SendMessage(embed->apiWindow, &message); } } diff --git a/res/Theme Source.dat b/res/Theme Source.dat index 012db0b33040e6d7c1e3f8ffcad9725c8159d979..55aca0761d478a75403d261bef5b27b80be2a194 100644 GIT binary patch delta 206 zcmaDgoq6F5<_*0nY%Pq9j43UX^_ECXUaca)$@Z_Kp{cQ&*pJz>U{$-N6CCO=UT zkb#MdF)%Q6H3JC`bvDN4$z9qqEFg)=^Ry*^hHcl@ zkcAm!2{a(30jEiu1$90%P1dvI7Gnb{EqlSqjQ;Q@&{er$qA~Qn+x?zXERmgZhmpfk`Vy81u-)K diff --git a/res/Themes/Theme.dat b/res/Themes/Theme.dat index bdd578a9030e1e63e78064d5f465200d7d56bb27..def7e345959418c261f0fa7d94f3ef0059600317 100644 GIT binary patch delta 3962 zcmZ9Pe@s+Y7RS%MGXrQ*!Lfy|Aio9$1Vz9?mC+&m8dn?#VVF^&4wbH;C{VFrmffK# zN!@B!*h_Y?#f`Q$vDQCuA4y51yKKTHY@}OE*pyAtwb7&`ORZ+vEN(IE_YN~K+(*9i z-u;~O&N=to`(_?PAL*t((uEF2{k5k*5+oKRP|(R}R;QJp~tM6?cn^5_Hmi=KP0 zJvbPS0kH23ddZmAfRB-`YNL4!hQ9_lOXCFC9sPoz3?SJg*q3@884UU$Kbz{hW%N9O z;jR*37VI;_QUx*qy+sreq$gRcKR_5*jKX5U%s~tHdhf$W64*bGJSfNz?7ue)>>Isq zHHF~tLyIV7Mso>F|5WO?gMEuK1HD~f5A_C_g~UCehQa=;WEv4& zh%g4rkBavM*mK2u5^O%ePxj%F_?8;(Od~jw35{g76b3V2c#D41>auwXKEBph|mg4LO^WU*mkhQ z046Iw2ewIJo#M}k&<)FGrG_4`w1t^*dB_OYz_uz8Zi;Y&(cA}1rV^naY&#+ZK50W> z*-C^FQH=;=u)L~77zf*_cu#_vmoY|<#4Q6h7%X>|Ti6U(p0du=N|dj#P_ROUMS>NB z$;01q6WAVwrGxD?;M*h6F;|oZ8O>IhzFt-mksWM5zCQh1Pu}GQyQQ#3aTO8TVJTB0 zoC9+xtP{+supaRg5w5^;Sg~9Ot5R4WSTVjpmo1mb3pScZU^%jE(u|FRRR=JJ2lfHj zQD0PVGw?Abx`K_K8CV`F`R2fmE&Pluwl@?%N+*;}5C)c}Jm>4cPAYzpU>6k@1=e6- zuX(HSuVE};lj3LsJFT!Jurmrv1v{z~lP=y4F`BbrX+cB$%POBj3)oqOm4N+RVJ>kO z5!|r68_-hu>sk-?3#D<*V4o;;wTieEMsp`DUj#t!c&c zwN6eWa5a&hZrr#rAB*$j$B*ZA#A&6EU%GV3%ST5?=k?%zf0;r0%fo=$Ga&!iB)*7h z;qB4le&iOdCOU_+QSEY!lW|j=_}fbx@?wZ+r8~v8>18aCq~!wY7Qk z`nk*(E6j0U^VWFrd()Pc&u0HOFX6LUVT(V+o`_H5W0EA45oHEhv8-$!hdy9DJv}`y zrs5mfuy!yZpYf1H#QOugB1#i~$8$EK(hL!`ae!I0zi-Uvyd&8=9cyv{XOr6doBzaF zueNVX1Y`Z;jjcbhYnmgyg|Qs*<+j^wM*CI9L%chQlUX0LN)f*ON9NL2z49UBv)Kro zqK#*V=vcG3x5L9`=758`i5`(H-49xz48G~KoHM7^U%fnK|yBiTJdtxMdbaosD<^3xZrK3K)ku?*KAZ&AJBMjnXpA>h|bDT@#Ij5Xx|VlzT31` zoGFVyxcAF+j7^HJ^7E`#i*~G$ZAhzV;WHH?C2WHjbLMcXQ`|4y!H1mUR7$!y?kwWu zS~Qlsq>*)sLf7ZaDxSOY*>x@N;Cdb2AF3)_xT(tT%38IwsymDq91*9oDm43%e$E?T z7b$f`qU7~SPBkLs=pT7jjj$d6K=fDJx#f*T2utWBhy`i7S`$h-K12C>2M9;?^l8nK0ko4g~t=z8VV zCAw)Lnn}Ui^(#ar*?4z_8lf@BnnQFQ8gme(R}hU>k6hzdm}A{x}^Q`knd1R8*1lZe_O zOERj#wB`AMZ`|!0yEh>pG~S5#3FM(U+?b05y--f+Qo>mzn=L_bl;2r}GkyftMWDYg zp;u773q_#E^-vh5+X#iB*jn`3z7{rU3KO!*zJ_58(P}Ic)Lw|fpt*v4qDox!7?B*B zz)j-?s2&SE6pk5TEQ5~jhkXtFpd^XC823Z=4D=5gl$!(FYzC6o zeVJ%a7TT8OL4VMbL1+jI)eV>h$#XY)ye<#UNI=+W52A5{9sjd#Ae!EdE?KZsaNT>ATS>=H=&SkTHbs1>pnqj=~Fd^%vGpP)NXk9PU&$Ikx)t0!a| delta 3887 zcmZ9Pe@vCv8OP6g@4es;YN3}_I)88xusBgsP_NaiI8k9T1?6(D7N=IGsHiYNFtfXw z(UmE!u;UiY`~y3e5XTnG%Tg0<%N9-Ah%F{2r76qWNHP*#s;TWrhhd*{;p*kQH{W~C z`8?12oaa2}y!Xe@yN;fB9SJ-9*MEOp2r&z_2ZU&7O>p~8)CqCGMu$xXR z+z)X{t`^w8T~5tp*uYzR>mIkS1H;Er&f3@oyX747(*ZQ=hTV2Lgv;fOiLjp5EAG%o z815JW`e1){J@aSEMlB)||X*%_LT5Gv|%~<|m6!9GFTVuWpu>Tq}wX0Sl zbYS_P;oSv$Vt9AMMx*?69j>ddEO+Pz7DrSL+R_Vi8SE}B)-`cu{jkXf8-V$Z3VaEh zYQ!6YJ?FCKhBrS_mWROSIqMFt$aamuE~*rVJ3S#PguZQ3y%7I2SiHL9aQhOmyg2^M zL}Ghj(+%$o*vkgXQYlWiF9*vkV`*MkGTzY-NG@#Z_*st3l&`9ZP=qBlDz+|c5SAXr z^eT44UNKmO`a2OSvCKDesDdpRTbZRV9pMCQkrAO$CAi$aCM?-Tgl5=MB1AuFZLsA= zgm$%u2pw2f7!f*QD-G{%m~R4;;<~!x;(%efHPIq_VQYeVbM}{!uCWl$pd>8ws$;g zxEQ?ksMc6_s29sUW4^nv{bOGvPs=+9J7gS!A=m=rIe!2M2NMTlG_z1Uqi9G}tc;mZk0x!Heas zsFLb$*F4x8M&Sx!e=_naQYn+&z6vbwM@L}YwXjpJ*r*Cf(E|IG5#gL&J^9HCMN)i( zYnpJ1%a<>YI>=$l`1t(!^P^725qmh|$!FuwFO-kEurEO#?$_7MS!#3Ak5pD}oJyRP zAscMpto@dCBUyd&(pWODwvJmBX>)CXxXZQR4;n~7twKL^2D>z4;-nwwg z@OR&j>d?dAsUvfC$UgP)oMexN*REX~wTPhe)ANsV=`8eE#iv%u3-+nhb<+AWjX3+% z!&HwdOwY6$(n)5vYD;gB@hV~NeVJrGnY+%CW%k;6HJ0qQ|2F?aOV-+T3#UujtlnPq zwLD?JkyS5o|90^;*=t`}a!*<$ zefFK@*$!E#Tq{GeSHD|@t5nR&Uov=e6$4*n;A5~_{n{6{tPV-1a;-Tl&)L6QbClz! zTpL!(T(x$?S+cmZpqXOX@dUZS1~n^;XxmaPD`v4O-nL>Vu=Ftz5ruRG+_* z3iwOw$@X?>!14rC%!XHGo7xkoxB3I>lhRU|sTK!U$_jNj_@4Br^zG~9N&CR|84i8~ zyjfOnjg*DGifsSRTWr3avTLeC=GzNiPnA~xUbS`a2Qp42l;5|Ker7LxeU6kJDrMh? z*1$e>?BHqHWFOw2s&}EaB3t&Tn-yndrCodgRAtv4+$61mL-s!o{nnBt%75ewoy*ZP z@~V2D_dL6xDj?+rb+P)4mGSfNvbw{KEK}=i-m`{l!mP12+{D*~SKMCb3}vhkBCA@6 z5;VAkM>1Q8Rl9_^fcjAn%A7AmGa5vVxkB{*ke|fMILXU7d?+7vAdgpwlc>YbkBU+u zF74s_-~ieyMBzamR*rk#ejzFtod#pdutj~9_Z789Tc3vga2!~lw0jME$;T1rR& z?!>Pgwf#hhqRl)dw2ibgYlIj%Bt)62J~kudrPqdrXY;FIw-7@tvGP^YMBQ73sCtg+ z)A$##ji~4${i1aK4UB7uHj5urEok@^A%Yn~B+VlmmaW^XlYy(yrJ^%O`i@be8@SHAQ(rlE|b*Lnwa%_mgZcwJv&re;cTW z1$n4zQ9NTLrm;vATu)-?Zr(Z}a_F?V`Qk9M<5q`6UxUq%@1DltAZ4Fgnv$|8p4nZPkS@$DndYEyf-?fAJsJ4?h<*2!gw-TI# zshku_Gx#E(_5~bQ6#Ow0qNGh!fm1Vra<`B9ByAulDng!(B!wEVH*&xD0jC93**A~> GG4Ovykw4A= diff --git a/shared/strings.cpp b/shared/strings.cpp index c3a1d45..96ce7c7 100644 --- a/shared/strings.cpp +++ b/shared/strings.cpp @@ -77,9 +77,6 @@ DEFINE_INTERFACE_STRING(CommonUnitMilliseconds, " ms"); // Desktop. -DEFINE_INTERFACE_STRING(DesktopCloseTab, "Close tab"); -DEFINE_INTERFACE_STRING(DesktopInspectUI, "Inspect UI"); -DEFINE_INTERFACE_STRING(DesktopCenterWindow, "Center in screen"); DEFINE_INTERFACE_STRING(DesktopNewTabTitle, "New Tab"); DEFINE_INTERFACE_STRING(DesktopShutdownTitle, "Shutdown"); DEFINE_INTERFACE_STRING(DesktopShutdownAction, "Shutdown"); @@ -91,6 +88,11 @@ DEFINE_INTERFACE_STRING(DesktopApplicationStartupError, "The requested applicati DEFINE_INTERFACE_STRING(DesktopNotResponding, "The application is not responding.\nIf you choose to force quit, any unsaved data may be lost."); DEFINE_INTERFACE_STRING(DesktopConfirmShutdown, "Are you sure you want to turn off your computer? All applications will be closed."); +DEFINE_INTERFACE_STRING(DesktopCloseTab, "Close tab"); +DEFINE_INTERFACE_STRING(DesktopMoveTabToNewWindow, "Move to new window"); +DEFINE_INTERFACE_STRING(DesktopInspectUI, "Inspect UI"); +DEFINE_INTERFACE_STRING(DesktopCenterWindow, "Center in screen"); + DEFINE_INTERFACE_STRING(DesktopSettingsApplication, "Settings"); DEFINE_INTERFACE_STRING(DesktopSettingsTitle, "Settings"); DEFINE_INTERFACE_STRING(DesktopSettingsBackButton, "All settings");