Skip to content

Commit 0186d85

Browse files
committed
hideo-shell: Implemented app switching.
1 parent 99a5ac2 commit 0186d85

File tree

12 files changed

+140
-57
lines changed

12 files changed

+140
-57
lines changed

src/apps/hideo-shell/app.h

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ inline auto panel(Math::Vec2i size = {500, 400}) {
1919
});
2020
}
2121

22+
Ui::Child background(State const &state);
23+
2224
Ui::Child lock(State const &state);
2325

2426
Ui::Child appsPanel(State const &state);

src/apps/hideo-shell/lock.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ Ui::Child lock(State const &state) {
1919
? "Swipe up to unlock"
2020
: "Swipe up or press any key to unlock")));
2121

22-
return Ui::vflow(clock, Ui::grow(NONE), hintText | Ui::slideIn(Ui::SlideFrom::BOTTOM)) |
23-
Ui::spacing(state.isMobile ? 64 : 128) |
24-
Ui::dragRegion() |
25-
Ui::dismisable(Model::bind<Unlock>(), Ui::DismisDir::TOP, 0.3) |
26-
Ui::align(Layout::Align::VFILL | Layout::Align::HCENTER);
22+
return Ui::stack(
23+
background(state),
24+
Ui::vflow(clock, Ui::grow(NONE), hintText | Ui::slideIn(Ui::SlideFrom::BOTTOM)) |
25+
Ui::spacing(state.isMobile ? 64 : 128) |
26+
Ui::dragRegion() |
27+
Ui::dismisable(Model::bind<Unlock>(), Ui::DismisDir::TOP, 0.3) |
28+
Ui::align(Layout::Align::VFILL | Layout::Align::HCENTER));
2729
}
2830

2931
} // namespace Shell

src/apps/hideo-shell/main.cpp

+29-12
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ Ui::Child statusbarButton(State const &) {
3838

3939
/* --- Navigation Bar ------------------------------------------------------- */
4040

41-
Ui::Child navbar(State const &state) {
42-
return state.activePanel != Panel::NIL ? Ui::empty() : Ui::buttonHandle(Model::bind<Activate>(Panel::APPS)) | Ui::slideIn(Ui::SlideFrom::BOTTOM);
41+
Ui::Child navbar(State const &) {
42+
return Ui::buttonHandle(
43+
Model::bind<Activate>(Panel::APPS)) |
44+
Ui::slideIn(Ui::SlideFrom::BOTTOM);
4345
}
4446

4547
/* --- Taskbar -------------------------------------------------------------- */
@@ -84,20 +86,38 @@ Ui::Child taskbar(State const &) {
8486

8587
/* --- Shells --------------------------------------------------------------- */
8688

89+
Ui::Child background(State const &state) {
90+
return Ui::image(state.background) |
91+
Ui::cover() | Ui::grow();
92+
}
93+
8794
Ui::Child tabletPanels(State const &state) {
8895
return Ui::stack(
8996
state.activePanel == Panel::APPS ? appsFlyout(state) : Ui::empty(),
9097
state.activePanel == Panel::SYS ? sysFlyout(state) : Ui::empty());
9198
}
9299

100+
Ui::Child appHost(State const &state) {
101+
if (state.surfaces.len() == 0) {
102+
return Ui::grow(NONE);
103+
}
104+
105+
auto &surface = state.surfaces[0];
106+
return Ui::empty() |
107+
Ui::box({.backgroundPaint = surface.color}) |
108+
Ui::grow();
109+
}
110+
93111
Ui::Child tablet(State const &state) {
94-
return Ui::vflow(
112+
return Ui::stack(
113+
state.surfaces.len() == 0 ? background(state) : Ui::empty(),
95114
Ui::vflow(
96-
statusbarButton(state),
97-
Ui::separator()) |
98-
Ui::slideIn(Ui::SlideFrom::TOP),
99-
Ui::grow(NONE),
100-
navbar(state));
115+
Ui::vflow(
116+
statusbarButton(state),
117+
Ui::separator()) |
118+
Ui::slideIn(Ui::SlideFrom::TOP),
119+
appHost(state),
120+
navbar(state)));
101121
}
102122

103123
Ui::Child desktopPanels(State const &state) {
@@ -121,6 +141,7 @@ Ui::Child app(bool isMobile) {
121141
return Ui::reducer<Model>(
122142
{
123143
.isMobile = isMobile,
144+
.background = Media::loadImageOrFallback("bundle://skift-wallpapers/images/abstract.qoi"_url).unwrap(),
124145
.noti = {
125146
{
126147
1,
@@ -207,11 +228,7 @@ Ui::Child app(bool isMobile) {
207228
},
208229
},
209230
[](auto state) {
210-
auto wallpapers = Media::loadImageOrFallback("bundle://skift-wallpapers/images/abstract.qoi"_url).unwrap();
211-
auto background = Ui::align(Layout::Align::COVER, Ui::image(wallpapers));
212-
213231
return Ui::stack(
214-
background,
215232
state.locked ? lock(state)
216233
: (state.isMobile ? tablet(state)
217234
: desktop(state)),

src/apps/hideo-shell/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
"skift-wallpapers",
1010
"hideo-keyboard"
1111
]
12-
}
12+
}

src/apps/hideo-shell/model.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ void reduce(State &s, Action a) {
1919
[&](DimisNoti dismis) {
2020
s.noti.removeAt(dismis.index);
2121
},
22+
[&](StartApp start) {
23+
s.activePanel = Panel::NIL;
24+
s.surfaces.emplaceFront(
25+
0,
26+
s.entries[start.index],
27+
Gfx::randomColor());
28+
},
29+
[&](CloseApp close) {
30+
s.surfaces.removeAt(close.index);
31+
},
32+
[&](FocusApp focus) {
33+
auto surface = s.surfaces.removeAt(focus.index);
34+
s.surfaces.pushFront(surface);
35+
s.activePanel = Panel::NIL;
36+
},
2237
[&](Activate panel) {
2338
if (s.activePanel != panel.panel) {
2439
s.activePanel = panel.panel;

src/apps/hideo-shell/model.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ enum struct Panel {
3030
};
3131

3232
struct Surface {
33+
usize id;
34+
MenuEntry entry;
35+
Gfx::Color color;
3336
};
3437

3538
struct State {
@@ -38,6 +41,7 @@ struct State {
3841
Panel activePanel = Panel::NIL;
3942
bool isSysPanelColapsed = true;
4043

44+
Media::Image background;
4145
Vec<Noti> noti;
4246
Vec<MenuEntry> entries;
4347
Vec<Surface> surfaces;
@@ -53,13 +57,25 @@ struct DimisNoti {
5357
usize index;
5458
};
5559

60+
struct StartApp {
61+
usize index;
62+
};
63+
64+
struct CloseApp {
65+
usize index;
66+
};
67+
68+
struct FocusApp {
69+
usize index;
70+
};
71+
5672
struct ToggleSysPanel {};
5773

5874
struct Activate {
5975
Panel panel;
6076
};
6177

62-
using Action = Var<ToggleTablet, Lock, Unlock, DimisNoti, Activate, ToggleSysPanel>;
78+
using Action = Var<ToggleTablet, Lock, Unlock, DimisNoti, StartApp, CloseApp, FocusApp, Activate, ToggleSysPanel>;
6379

6480
void reduce(State &, Action);
6581

src/apps/hideo-shell/tray-apps.cpp

+49-27
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,36 @@ Ui::Child appIcon(MenuIcon const &icon, isize size = 22) {
3838
});
3939
}
4040

41-
Ui::Child appRow(MenuEntry const &entry) {
42-
return Ui::button(
43-
Ui::NOP,
44-
Ui::ButtonStyle::subtle(),
45-
Ui::hflow(
46-
12,
47-
Layout::Align::START | Layout::Align::VCENTER,
48-
appIcon(entry.icon),
49-
Ui::labelLarge(entry.name)) |
50-
Ui::spacing(6));
41+
Ui::Child appRow(MenuEntry const &entry, usize i) {
42+
return Ui::ButtonStyle::subtle(),
43+
Ui::hflow(
44+
12,
45+
Layout::Align::START | Layout::Align::VCENTER,
46+
appIcon(entry.icon),
47+
Ui::labelLarge(entry.name)) |
48+
Ui::spacing(6) | Ui::button(Model::bind<StartApp>(i), Ui::ButtonStyle::subtle());
49+
}
50+
51+
Ui::Child runningApp(Surface const &surface, usize i) {
52+
return Ui::stack(
53+
appIcon(surface.entry.icon) |
54+
Ui::bound() |
55+
Ui::button(Model::bind<FocusApp>(i)),
56+
Ui::button(Model::bind<CloseApp>(i), Ui::ButtonStyle::secondary(), Mdi::CLOSE) |
57+
Ui::align(Layout::Align::TOP_END) |
58+
Ui::spacing({0, 6, 6, 0})) |
59+
Ui::pinSize({120, 192});
60+
}
61+
62+
Ui::Child runningApps(State const &state) {
63+
if (state.surfaces.len() == 0)
64+
return Ui::empty(64);
65+
return Ui::hflow(
66+
8,
67+
iter(state.surfaces)
68+
.mapi(runningApp)
69+
.collect<Ui::Children>()) |
70+
Ui::center() | Ui::spacing({0, 64, 0, 16});
5171
}
5272

5373
Ui::Child apps(Ui::Children apps) {
@@ -66,7 +86,7 @@ Ui::Child apps(Ui::Children apps) {
6686
Ui::Child appsList(State const &state) {
6787
return apps(
6888
iter(state.entries)
69-
.map(appRow)
89+
.mapi(appRow)
7090
.collect<Ui::Children>());
7191
}
7292

@@ -76,22 +96,24 @@ Ui::Child appsPanel(State const &state) {
7696

7797
Ui::Child appsFlyout(State const &state) {
7898
return Ui::vflow(
79-
Ui::dragHandle(),
80-
appsList(state) | Ui::grow()) |
81-
Ui::box({
82-
.margin = {8, 8 + 64, 8, 8},
83-
.padding = {12, 0},
84-
.borderRadius = 8,
85-
.borderWidth = 1,
86-
.borderPaint = Ui::GRAY800,
87-
.backgroundPaint = Ui::GRAY950,
88-
}) |
89-
Ui::bound() |
90-
Ui::dismisable(
91-
Model::bind<Activate>(Panel::NIL),
92-
Ui::DismisDir::DOWN,
93-
0.3) |
94-
Ui::slideIn(Ui::SlideFrom::BOTTOM);
99+
runningApps(state),
100+
Ui::vflow(
101+
Ui::dragHandle(),
102+
appsList(state) | Ui::grow()) |
103+
Ui::box({
104+
.margin = {8, 8, 8, 8},
105+
.padding = {12, 0},
106+
.borderRadius = 8,
107+
.borderWidth = 1,
108+
.borderPaint = Ui::GRAY800,
109+
.backgroundPaint = Ui::GRAY950,
110+
}) |
111+
Ui::bound() |
112+
Ui::dismisable(
113+
Model::bind<Activate>(Panel::NIL),
114+
Ui::DismisDir::DOWN,
115+
0.3) |
116+
Ui::slideIn(Ui::SlideFrom::BOTTOM) | Ui::grow());
95117
}
96118

97119
} // namespace Shell

src/libs/karm-base/vec.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct _Vec {
8989

9090
T const &peekFront() const { return _buf[0]; }
9191

92-
void pushFront(T const &value) { _buf.insert(T(value)); }
92+
void pushFront(T const &value) { _buf.insert(0, T(value)); }
9393

9494
void pushFront(T &&value) { _buf.insert(0, std::move(value)); }
9595

src/libs/karm-gfx/colors.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ inline Color randomColor(Math::Rand &rand) {
7575
}
7676

7777
inline Color randomColor() {
78-
static Math::Rand rand;
78+
static Math::Rand rand{123};
7979
return randomColor(rand);
8080
}
8181

src/libs/karm-layout/align.h

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ struct Align {
2121
static constexpr u16 HCLAMP = (1 << 10);
2222
static constexpr u16 VCLAMP = (1 << 11);
2323

24+
static constexpr u16 TOP_START = (TOP | START);
25+
static constexpr u16 TOP_END = (TOP | END);
26+
static constexpr u16 BOTTOM_START = (BOTTOM | START);
27+
static constexpr u16 BOTTOM_END = (BOTTOM | END);
28+
2429
static constexpr u16 STRETCH = (HSTRETCH | VSTRETCH);
2530
static constexpr u16 VFILL = (VSTRETCH | TOP);
2631
static constexpr u16 HFILL = (HSTRETCH | START);

src/libs/karm-ui/drag.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ struct Dismisable :
2828
_onDismis = std::move(o._onDismis);
2929
_dir = o._dir;
3030
_threshold = o._threshold;
31+
32+
ProxyNode<Dismisable>::reconcile(o);
3133
}
3234

3335
Math::Vec2i drag() const {
@@ -52,16 +54,23 @@ struct Dismisable :
5254
}
5355

5456
void event(Async::Event &e) override {
55-
auto oldBound = bound().clipTo(child().bound().offset(_last));
56-
if (_dismissed and _drag.reached()) {
57+
if (auto *me = e.is<Events::MouseEvent>()) {
58+
me->pos = me->pos - drag();
59+
child().event(e);
60+
me->pos = me->pos + drag();
61+
} else if (e.is<Node::AnimateEvent>() and _dismissed and _drag.reached()) {
5762
_onDismis(*this);
5863
_dismissed = false;
64+
Ui::ProxyNode<Dismisable>::event(e);
5965
} else if (_drag.needRepaint(*this, e)) {
66+
auto oldBound = bound().clipTo(child().bound().offset(_last));
6067
auto newBound = bound().clipTo(child().bound().offset(drag()));
6168
_last = drag();
6269
Ui::shouldRepaint(*this, oldBound.mergeWith(newBound));
70+
Ui::ProxyNode<Dismisable>::event(e);
71+
} else {
72+
Ui::ProxyNode<Dismisable>::event(e);
6373
}
64-
Ui::ProxyNode<Dismisable>::event(e);
6574
}
6675

6776
void bubble(Async::Event &e) override {

src/libs/karm-ui/scafold.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,7 @@ Child scafold(Scafold scafold) {
163163

164164
return vflow(appBody) |
165165
pinSize(state.isMobile ? Math::Vec2i{411, 731} : scafold.size) |
166-
dialogLayer() |
167-
Ui::box(Ui::BoxStyle{
168-
.borderRadius = 6,
169-
.borderWidth = 1,
170-
.borderPaint = Ui::GRAY800,
171-
});
166+
dialogLayer();
172167
});
173168
}
174169

0 commit comments

Comments
 (0)