Skip to main content

slowshell_plugin_abi/
surfaces.rs

1use std::marker::PhantomData;
2
3use abi_stable::{
4  StableAbi, sabi_trait,
5  sabi_trait::TD_Opaque,
6  std_types::{RBox, ROption, RResult, RStr, RString, RVec},
7};
8
9use crate::{
10  event::{Args, Event, EventFilter, ItemEffect, Message},
11  host::Context,
12  payload::PayloadBox,
13  types::{
14    DesktopSettings, DisplayStyle, Node, QuickSettingsTile, RenderableSettings, SpotlightResult,
15  },
16};
17
18pub trait Component: Send + 'static {
19  fn new(ctx: &Context<'_>) -> Self;
20  fn events(&self) -> RVec<EventFilter> {
21    RVec::new()
22  }
23  fn foreground_services(&self) -> RVec<RString> {
24    RVec::new()
25  }
26  fn watch(&mut self, _ctx: &Context<'_>) {}
27  fn update(&mut self, _ctx: &Context<'_>, _event: &Event) -> ItemEffect {
28    ItemEffect::None
29  }
30  fn check_view(&self, _ctx: &Context<'_>) -> bool {
31    true
32  }
33  fn hoverable() -> bool {
34    true
35  }
36  fn stop(&mut self, _ctx: &Context<'_>) {}
37  fn view(&self, ctx: &Context<'_>) -> Node;
38}
39
40#[sabi_trait]
41pub trait ComponentObject: Send + 'static {
42  fn events(&self) -> RVec<EventFilter>;
43  fn foreground_services(&self) -> RVec<RString>;
44  fn watch(&mut self, ctx: &Context<'_>);
45  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect;
46  fn check_view(&self, ctx: &Context<'_>) -> bool;
47  fn stop(&mut self, ctx: &Context<'_>);
48  fn view(&self, ctx: &Context<'_>) -> Node;
49}
50
51pub type ComponentObjectBox = ComponentObject_TO<RBox<()>>;
52
53#[sabi_trait]
54pub trait ComponentFactory: Send + Sync + 'static {
55  fn create(&self, ctx: &Context<'_>) -> ComponentObjectBox;
56  fn hoverable(&self) -> bool;
57}
58
59pub type ComponentFactoryBox = ComponentFactory_TO<RBox<()>>;
60
61struct ComponentAdapter<T>(T);
62
63impl<T: Component> ComponentObject for ComponentAdapter<T> {
64  fn events(&self) -> RVec<EventFilter> {
65    self.0.events()
66  }
67
68  fn foreground_services(&self) -> RVec<RString> {
69    self.0.foreground_services()
70  }
71
72  fn watch(&mut self, ctx: &Context<'_>) {
73    self.0.watch(ctx);
74  }
75
76  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect {
77    self.0.update(ctx, event)
78  }
79
80  fn check_view(&self, ctx: &Context<'_>) -> bool {
81    self.0.check_view(ctx)
82  }
83
84  fn stop(&mut self, ctx: &Context<'_>) {
85    self.0.stop(ctx);
86  }
87
88  fn view(&self, ctx: &Context<'_>) -> Node {
89    self.0.view(ctx)
90  }
91}
92
93struct ComponentFactoryImpl<T>(PhantomData<fn() -> T>);
94
95impl<T: Component> ComponentFactory for ComponentFactoryImpl<T> {
96  fn create(&self, ctx: &Context<'_>) -> ComponentObjectBox {
97    ComponentObjectBox::from_value(ComponentAdapter(T::new(ctx)), TD_Opaque)
98  }
99
100  fn hoverable(&self) -> bool {
101    T::hoverable()
102  }
103}
104
105pub fn component_factory<T: Component>() -> ComponentFactoryBox {
106  ComponentFactoryBox::from_value(ComponentFactoryImpl::<T>(PhantomData), TD_Opaque)
107}
108
109pub trait Renderable: Send + 'static {
110  fn new(ctx: &Context<'_>) -> Self;
111  fn settings(&self) -> RenderableSettings {
112    RenderableSettings::default()
113  }
114  fn events(&self) -> RVec<EventFilter> {
115    RVec::new()
116  }
117  fn initialize(&mut self, _ctx: &Context<'_>) {}
118  fn update(&mut self, _ctx: &Context<'_>) -> ItemEffect {
119    ItemEffect::None
120  }
121  fn on_event(&mut self, _ctx: &Context<'_>, _event: &Event) -> ItemEffect {
122    ItemEffect::None
123  }
124  fn handle_message(&mut self, _ctx: &Context<'_>, _message: &Message) -> ItemEffect {
125    ItemEffect::None
126  }
127  fn view(&self, ctx: &Context<'_>) -> Node;
128}
129
130#[sabi_trait]
131pub trait RenderableObject: Send + 'static {
132  fn settings(&self) -> RenderableSettings;
133  fn events(&self) -> RVec<EventFilter>;
134  fn initialize(&mut self, ctx: &Context<'_>);
135  fn update(&mut self, ctx: &Context<'_>) -> ItemEffect;
136  fn on_event(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect;
137  fn handle_message(&mut self, ctx: &Context<'_>, message: &Message) -> ItemEffect;
138  fn view(&self, ctx: &Context<'_>) -> Node;
139}
140
141pub type RenderableObjectBox = RenderableObject_TO<RBox<()>>;
142
143#[sabi_trait]
144pub trait RenderableFactory: Send + Sync + 'static {
145  fn create(&self, ctx: &Context<'_>) -> RenderableObjectBox;
146}
147
148pub type RenderableFactoryBox = RenderableFactory_TO<RBox<()>>;
149
150struct RenderableAdapter<T>(T);
151
152impl<T: Renderable> RenderableObject for RenderableAdapter<T> {
153  fn settings(&self) -> RenderableSettings {
154    self.0.settings()
155  }
156
157  fn events(&self) -> RVec<EventFilter> {
158    self.0.events()
159  }
160
161  fn initialize(&mut self, ctx: &Context<'_>) {
162    self.0.initialize(ctx);
163  }
164
165  fn update(&mut self, ctx: &Context<'_>) -> ItemEffect {
166    self.0.update(ctx)
167  }
168
169  fn on_event(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect {
170    self.0.on_event(ctx, event)
171  }
172
173  fn handle_message(&mut self, ctx: &Context<'_>, message: &Message) -> ItemEffect {
174    self.0.handle_message(ctx, message)
175  }
176
177  fn view(&self, ctx: &Context<'_>) -> Node {
178    self.0.view(ctx)
179  }
180}
181
182struct RenderableFactoryImpl<T>(PhantomData<fn() -> T>);
183
184impl<T: Renderable> RenderableFactory for RenderableFactoryImpl<T> {
185  fn create(&self, ctx: &Context<'_>) -> RenderableObjectBox {
186    RenderableObjectBox::from_value(RenderableAdapter(T::new(ctx)), TD_Opaque)
187  }
188}
189
190pub fn renderable_factory<T: Renderable>() -> RenderableFactoryBox {
191  RenderableFactoryBox::from_value(RenderableFactoryImpl::<T>(PhantomData), TD_Opaque)
192}
193
194pub trait Payload: Send + 'static {
195  fn new(ctx: &Context<'_>) -> Self;
196  fn invoke(&mut self, ctx: &Context<'_>, args: &Args, payload: ROption<&PayloadBox>);
197}
198
199#[sabi_trait]
200pub trait PayloadObject: Send + 'static {
201  fn invoke(&mut self, ctx: &Context<'_>, args: &Args, payload: ROption<&PayloadBox>);
202}
203
204pub type PayloadObjectBox = PayloadObject_TO<RBox<()>>;
205
206#[sabi_trait]
207pub trait PayloadFactory: Send + Sync + 'static {
208  fn create(&self, ctx: &Context<'_>) -> PayloadObjectBox;
209}
210
211pub type PayloadFactoryBox = PayloadFactory_TO<RBox<()>>;
212
213struct PayloadAdapter<T>(T);
214
215impl<T: Payload> PayloadObject for PayloadAdapter<T> {
216  fn invoke(&mut self, ctx: &Context<'_>, args: &Args, payload: ROption<&PayloadBox>) {
217    self.0.invoke(ctx, args, payload);
218  }
219}
220
221struct PayloadFactoryImpl<T>(PhantomData<fn() -> T>);
222
223impl<T: Payload> PayloadFactory for PayloadFactoryImpl<T> {
224  fn create(&self, ctx: &Context<'_>) -> PayloadObjectBox {
225    PayloadObjectBox::from_value(PayloadAdapter(T::new(ctx)), TD_Opaque)
226  }
227}
228
229pub fn payload_factory<T: Payload>() -> PayloadFactoryBox {
230  PayloadFactoryBox::from_value(PayloadFactoryImpl::<T>(PhantomData), TD_Opaque)
231}
232
233pub trait DesktopItem: Send + 'static {
234  fn new(ctx: &Context<'_>) -> Self;
235  fn settings(&self) -> DesktopSettings;
236  fn events(&self) -> RVec<EventFilter> {
237    RVec::new()
238  }
239  fn initialize(&mut self, _ctx: &Context<'_>) {}
240  fn update(&mut self, _ctx: &Context<'_>, _event: &Event) -> ItemEffect {
241    ItemEffect::None
242  }
243  fn view(&self, ctx: &Context<'_>) -> Node;
244  fn handle_message(&mut self, _ctx: &Context<'_>, _message: &Message) -> ItemEffect {
245    ItemEffect::None
246  }
247}
248
249#[sabi_trait]
250pub trait DesktopItemObject: Send + 'static {
251  fn settings(&self) -> DesktopSettings;
252  fn events(&self) -> RVec<EventFilter>;
253  fn initialize(&mut self, ctx: &Context<'_>);
254  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect;
255  fn view(&self, ctx: &Context<'_>) -> Node;
256  fn handle_message(&mut self, ctx: &Context<'_>, message: &Message) -> ItemEffect;
257}
258
259pub type DesktopItemObjectBox = DesktopItemObject_TO<RBox<()>>;
260
261#[sabi_trait]
262pub trait DesktopItemFactory: Send + Sync + 'static {
263  fn create(&self, ctx: &Context<'_>) -> DesktopItemObjectBox;
264}
265
266pub type DesktopItemFactoryBox = DesktopItemFactory_TO<RBox<()>>;
267
268struct DesktopItemAdapter<T>(T);
269
270impl<T: DesktopItem> DesktopItemObject for DesktopItemAdapter<T> {
271  fn settings(&self) -> DesktopSettings {
272    self.0.settings()
273  }
274
275  fn events(&self) -> RVec<EventFilter> {
276    self.0.events()
277  }
278
279  fn initialize(&mut self, ctx: &Context<'_>) {
280    self.0.initialize(ctx);
281  }
282
283  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> ItemEffect {
284    self.0.update(ctx, event)
285  }
286
287  fn view(&self, ctx: &Context<'_>) -> Node {
288    self.0.view(ctx)
289  }
290
291  fn handle_message(&mut self, ctx: &Context<'_>, message: &Message) -> ItemEffect {
292    self.0.handle_message(ctx, message)
293  }
294}
295
296struct DesktopItemFactoryImpl<T>(PhantomData<fn() -> T>);
297
298impl<T: DesktopItem> DesktopItemFactory for DesktopItemFactoryImpl<T> {
299  fn create(&self, ctx: &Context<'_>) -> DesktopItemObjectBox {
300    DesktopItemObjectBox::from_value(DesktopItemAdapter(T::new(ctx)), TD_Opaque)
301  }
302}
303
304pub fn desktop_item_factory<T: DesktopItem>() -> DesktopItemFactoryBox {
305  DesktopItemFactoryBox::from_value(DesktopItemFactoryImpl::<T>(PhantomData), TD_Opaque)
306}
307
308#[repr(C)]
309#[derive(StableAbi)]
310pub struct DeployedItem {
311  pub id: RString,
312  pub item: DesktopItemObjectBox,
313}
314
315impl DeployedItem {
316  pub fn new<T: DesktopItem>(ctx: &Context<'_>, id: impl Into<RString>) -> Self {
317    Self {
318      id: id.into(),
319      item: desktop_item_factory::<T>().create(ctx),
320    }
321  }
322}
323
324#[repr(C)]
325#[derive(StableAbi)]
326pub enum DeployResult {
327  None,
328  Deploy(RVec<DeployedItem>),
329  Destroy(RString),
330  Many(RVec<DeployResult>),
331}
332
333pub trait DeployableDesktopItem: Send + 'static {
334  fn new(ctx: &Context<'_>) -> Self;
335  fn events(&self) -> RVec<EventFilter> {
336    RVec::new()
337  }
338  fn deploy(&mut self, _ctx: &Context<'_>, _event: &Event) -> DeployResult {
339    DeployResult::None
340  }
341}
342
343#[sabi_trait]
344pub trait DeployableDesktopItemObject: Send + 'static {
345  fn events(&self) -> RVec<EventFilter>;
346  fn deploy(&mut self, ctx: &Context<'_>, event: &Event) -> DeployResult;
347}
348
349pub type DeployableDesktopItemObjectBox = DeployableDesktopItemObject_TO<RBox<()>>;
350
351#[sabi_trait]
352pub trait DeployableDesktopItemFactory: Send + Sync + 'static {
353  fn create(&self, ctx: &Context<'_>) -> DeployableDesktopItemObjectBox;
354}
355
356pub type DeployableDesktopItemFactoryBox = DeployableDesktopItemFactory_TO<RBox<()>>;
357
358struct DeployableDesktopItemAdapter<T>(T);
359
360impl<T: DeployableDesktopItem> DeployableDesktopItemObject for DeployableDesktopItemAdapter<T> {
361  fn events(&self) -> RVec<EventFilter> {
362    self.0.events()
363  }
364
365  fn deploy(&mut self, ctx: &Context<'_>, event: &Event) -> DeployResult {
366    self.0.deploy(ctx, event)
367  }
368}
369
370struct DeployableDesktopItemFactoryImpl<T>(PhantomData<fn() -> T>);
371
372impl<T: DeployableDesktopItem> DeployableDesktopItemFactory
373  for DeployableDesktopItemFactoryImpl<T>
374{
375  fn create(&self, ctx: &Context<'_>) -> DeployableDesktopItemObjectBox {
376    DeployableDesktopItemObjectBox::from_value(DeployableDesktopItemAdapter(T::new(ctx)), TD_Opaque)
377  }
378}
379
380pub fn deployable_desktop_item_factory<T: DeployableDesktopItem>() -> DeployableDesktopItemFactoryBox
381{
382  DeployableDesktopItemFactoryBox::from_value(
383    DeployableDesktopItemFactoryImpl::<T>(PhantomData),
384    TD_Opaque,
385  )
386}
387
388#[repr(C)]
389#[derive(StableAbi, Clone, Debug)]
390pub enum CompositorCommand {
391  FocusWorkspace(i32),
392  FocusWindow(u64),
393  CloseWindow(u64),
394  KillWindow(u64),
395  FocusMonitor(RString),
396  Custom(PayloadBox),
397}
398
399pub trait Compositor: Send + 'static {
400  fn new(ctx: &Context<'_>) -> Self;
401  fn is_active(&self) -> bool {
402    false
403  }
404  fn initialize(&mut self, _ctx: &Context<'_>) {}
405  fn update_state(&mut self, _ctx: &Context<'_>) {}
406  fn send_command(&mut self, _ctx: &Context<'_>, _command: &CompositorCommand) {}
407}
408
409#[sabi_trait]
410pub trait CompositorObject: Send + 'static {
411  fn is_active(&self) -> bool;
412  fn initialize(&mut self, ctx: &Context<'_>);
413  fn update_state(&mut self, ctx: &Context<'_>);
414  fn send_command(&mut self, ctx: &Context<'_>, command: &CompositorCommand);
415}
416
417pub type CompositorObjectBox = CompositorObject_TO<RBox<()>>;
418
419#[sabi_trait]
420pub trait CompositorFactory: Send + Sync + 'static {
421  fn create(&self, ctx: &Context<'_>) -> CompositorObjectBox;
422}
423
424pub type CompositorFactoryBox = CompositorFactory_TO<RBox<()>>;
425
426struct CompositorAdapter<T>(T);
427
428impl<T: Compositor> CompositorObject for CompositorAdapter<T> {
429  fn is_active(&self) -> bool {
430    self.0.is_active()
431  }
432
433  fn initialize(&mut self, ctx: &Context<'_>) {
434    self.0.initialize(ctx);
435  }
436
437  fn update_state(&mut self, ctx: &Context<'_>) {
438    self.0.update_state(ctx);
439  }
440
441  fn send_command(&mut self, ctx: &Context<'_>, command: &CompositorCommand) {
442    self.0.send_command(ctx, command);
443  }
444}
445
446struct CompositorFactoryImpl<T>(PhantomData<fn() -> T>);
447
448impl<T: Compositor> CompositorFactory for CompositorFactoryImpl<T> {
449  fn create(&self, ctx: &Context<'_>) -> CompositorObjectBox {
450    CompositorObjectBox::from_value(CompositorAdapter(T::new(ctx)), TD_Opaque)
451  }
452}
453
454pub fn compositor_factory<T: Compositor>() -> CompositorFactoryBox {
455  CompositorFactoryBox::from_value(CompositorFactoryImpl::<T>(PhantomData), TD_Opaque)
456}
457
458pub trait Spotlight: Send + 'static {
459  fn new(ctx: &Context<'_>) -> Self;
460  fn generate(&mut self, _ctx: &Context<'_>, _query: &str) -> Vec<SpotlightResult> {
461    Vec::new()
462  }
463  fn activate(&mut self, _ctx: &Context<'_>, _index: usize) {}
464  fn trigger_check(&self, _ctx: &Context<'_>, _query: &str) -> bool {
465    false
466  }
467  fn allows_triggers() -> bool {
468    false
469  }
470  fn display_styles() -> &'static [DisplayStyle] {
471    &[DisplayStyle::List]
472  }
473}
474
475#[sabi_trait]
476pub trait SpotlightObject: Send + 'static {
477  fn generate(&mut self, ctx: &Context<'_>, query: RStr<'_>) -> RVec<SpotlightResult>;
478  fn activate(&mut self, ctx: &Context<'_>, index: usize);
479  fn trigger_check(&self, ctx: &Context<'_>, query: RStr<'_>) -> bool;
480  fn allows_triggers(&self) -> bool;
481  fn display_styles(&self) -> u32;
482}
483
484pub type SpotlightObjectBox = SpotlightObject_TO<RBox<()>>;
485
486#[sabi_trait]
487pub trait SpotlightFactory: Send + Sync + 'static {
488  fn create(&self, ctx: &Context<'_>) -> SpotlightObjectBox;
489}
490
491pub type SpotlightFactoryBox = SpotlightFactory_TO<RBox<()>>;
492
493struct SpotlightAdapter<T>(T);
494
495impl<T: Spotlight> SpotlightObject for SpotlightAdapter<T> {
496  fn generate(&mut self, ctx: &Context<'_>, query: RStr<'_>) -> RVec<SpotlightResult> {
497    self.0.generate(ctx, &query).into()
498  }
499
500  fn activate(&mut self, ctx: &Context<'_>, index: usize) {
501    self.0.activate(ctx, index);
502  }
503
504  fn trigger_check(&self, ctx: &Context<'_>, query: RStr<'_>) -> bool {
505    self.0.trigger_check(ctx, &query)
506  }
507
508  fn allows_triggers(&self) -> bool {
509    T::allows_triggers()
510  }
511
512  fn display_styles(&self) -> u32 {
513    T::display_styles()
514      .iter()
515      .fold(0, |bits, style| bits | style.bit())
516  }
517}
518
519struct SpotlightFactoryImpl<T>(PhantomData<fn() -> T>);
520
521impl<T: Spotlight> SpotlightFactory for SpotlightFactoryImpl<T> {
522  fn create(&self, ctx: &Context<'_>) -> SpotlightObjectBox {
523    SpotlightObjectBox::from_value(SpotlightAdapter(T::new(ctx)), TD_Opaque)
524  }
525}
526
527pub fn spotlight_factory<T: Spotlight>() -> SpotlightFactoryBox {
528  SpotlightFactoryBox::from_value(SpotlightFactoryImpl::<T>(PhantomData), TD_Opaque)
529}
530
531pub trait QuickSettings: Send + 'static {
532  fn new(ctx: &Context<'_>) -> Self;
533  fn tiles(&self, _ctx: &Context<'_>) -> Vec<QuickSettingsTile> {
534    Vec::new()
535  }
536  fn children(&self, _ctx: &Context<'_>, _id: &str) -> Vec<QuickSettingsTile> {
537    Vec::new()
538  }
539}
540
541#[sabi_trait]
542pub trait QuickSettingsObject: Send + 'static {
543  fn tiles(&self, ctx: &Context<'_>) -> RVec<QuickSettingsTile>;
544  fn children(&self, ctx: &Context<'_>, id: RStr<'_>) -> RVec<QuickSettingsTile>;
545}
546
547pub type QuickSettingsObjectBox = QuickSettingsObject_TO<RBox<()>>;
548
549#[sabi_trait]
550pub trait QuickSettingsFactory: Send + Sync + 'static {
551  fn create(&self, ctx: &Context<'_>) -> QuickSettingsObjectBox;
552}
553
554pub type QuickSettingsFactoryBox = QuickSettingsFactory_TO<RBox<()>>;
555
556struct QuickSettingsAdapter<T>(T);
557
558impl<T: QuickSettings> QuickSettingsObject for QuickSettingsAdapter<T> {
559  fn tiles(&self, ctx: &Context<'_>) -> RVec<QuickSettingsTile> {
560    self.0.tiles(ctx).into()
561  }
562
563  fn children(&self, ctx: &Context<'_>, id: RStr<'_>) -> RVec<QuickSettingsTile> {
564    self.0.children(ctx, &id).into()
565  }
566}
567
568struct QuickSettingsFactoryImpl<T>(PhantomData<fn() -> T>);
569
570impl<T: QuickSettings> QuickSettingsFactory for QuickSettingsFactoryImpl<T> {
571  fn create(&self, ctx: &Context<'_>) -> QuickSettingsObjectBox {
572    QuickSettingsObjectBox::from_value(QuickSettingsAdapter(T::new(ctx)), TD_Opaque)
573  }
574}
575
576pub fn quick_settings_factory<T: QuickSettings>() -> QuickSettingsFactoryBox {
577  QuickSettingsFactoryBox::from_value(QuickSettingsFactoryImpl::<T>(PhantomData), TD_Opaque)
578}
579
580#[sabi_trait]
581pub trait ConfigParser: Send + Sync + 'static {
582  fn parse(
583    &self,
584    block: abi_stable::std_types::ROption<RStr<'_>>,
585  ) -> RResult<(), abi_stable::std_types::RString>;
586}
587
588pub type ConfigParserBox = ConfigParser_TO<RBox<()>>;
589
590pub trait Service: Send + 'static {
591  fn new(ctx: &Context<'_>) -> Self;
592  fn run(&mut self, ctx: &crate::host::ServiceContext<'_>);
593}
594
595#[sabi_trait]
596pub trait ServiceObject: Send + 'static {
597  fn run(&mut self, ctx: &crate::host::ServiceContext<'_>);
598}
599
600pub type ServiceObjectBox = ServiceObject_TO<RBox<()>>;
601
602#[sabi_trait]
603pub trait ServiceFactory: Send + Sync + 'static {
604  fn create(&self, ctx: &Context<'_>) -> ServiceObjectBox;
605}
606
607pub type ServiceFactoryBox = ServiceFactory_TO<RBox<()>>;
608
609struct ServiceAdapter<T>(T);
610
611impl<T: Service> ServiceObject for ServiceAdapter<T> {
612  fn run(&mut self, ctx: &crate::host::ServiceContext<'_>) {
613    self.0.run(ctx);
614  }
615}
616
617struct ServiceFactoryImpl<T>(PhantomData<fn() -> T>);
618
619impl<T: Service> ServiceFactory for ServiceFactoryImpl<T> {
620  fn create(&self, ctx: &Context<'_>) -> ServiceObjectBox {
621    ServiceObjectBox::from_value(ServiceAdapter(T::new(ctx)), TD_Opaque)
622  }
623}
624
625pub fn service_factory<T: Service>() -> ServiceFactoryBox {
626  ServiceFactoryBox::from_value(ServiceFactoryImpl::<T>(PhantomData), TD_Opaque)
627}
628
629pub trait ForegroundService: Send + 'static {
630  fn new(ctx: &Context<'_>) -> Self;
631  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> bool;
632}
633
634#[sabi_trait]
635pub trait ForegroundServiceObject: Send + 'static {
636  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> bool;
637}
638
639pub type ForegroundServiceObjectBox = ForegroundServiceObject_TO<RBox<()>>;
640
641#[sabi_trait]
642pub trait ForegroundServiceFactory: Send + Sync + 'static {
643  fn create(&self, ctx: &Context<'_>) -> ForegroundServiceObjectBox;
644}
645
646pub type ForegroundServiceFactoryBox = ForegroundServiceFactory_TO<RBox<()>>;
647
648struct ForegroundServiceAdapter<T>(T);
649
650impl<T: ForegroundService> ForegroundServiceObject for ForegroundServiceAdapter<T> {
651  fn update(&mut self, ctx: &Context<'_>, event: &Event) -> bool {
652    self.0.update(ctx, event)
653  }
654}
655
656struct ForegroundServiceFactoryImpl<T>(PhantomData<fn() -> T>);
657
658impl<T: ForegroundService> ForegroundServiceFactory for ForegroundServiceFactoryImpl<T> {
659  fn create(&self, ctx: &Context<'_>) -> ForegroundServiceObjectBox {
660    ForegroundServiceObjectBox::from_value(ForegroundServiceAdapter(T::new(ctx)), TD_Opaque)
661  }
662}
663
664pub fn foreground_service_factory<T: ForegroundService>() -> ForegroundServiceFactoryBox {
665  ForegroundServiceFactoryBox::from_value(ForegroundServiceFactoryImpl::<T>(PhantomData), TD_Opaque)
666}