popup_surface.go RawHistoryFolder
1package cef
2
3import (
4 "context"
5 "sync/atomic"
6
7 purecef "github.com/bnema/purego-cef/cef"
8 cef2gtk "github.com/bnema/purego-cef2gtk"
9 "github.com/bnema/puregotk/v4/glib"
10 "github.com/bnema/puregotk/v4/gtk"
11
12 "github.com/bnema/dumber/internal/logging"
13)
14
15type popupBridgeSurface struct {
16 ctx context.Context
17 root *gtk.Widget
18 mainWidget *gtk.Widget
19 bridge *Cef2gtkAdapter
20 popupWidget *gtk.Widget
21 prepared atomic.Uint32
22}
23
24// newPopupBridgeSurface must be called on the GTK thread because it creates
25// and packs GTK widgets around the primary CEF widget.
26func newPopupBridgeSurface(
27 ctx context.Context,
28 mainWidget *gtk.Widget,
29 plan cef2gtk.RenderStackPlan,
30 applicationScale float64,
31) *popupBridgeSurface {
32 mainContext := glib.MainContextDefault()
33 if mainContext == nil || !mainContext.IsOwner() {
34 logging.FromContext(popupSurfaceLogContext(ctx)).Error().Msg("cef: newPopupBridgeSurface called off GTK thread")
35 return nil
36 }
37 if mainWidget == nil {
38 return nil
39 }
40 bridge := NewCef2gtkAdapter(plan, applicationScale)
41 if bridge == nil {
42 return nil
43 }
44 popupWidget := bridge.Widget()
45 if popupWidget == nil {
46 _ = bridge.Destroy()
47 return nil
48 }
49 overlay := gtk.NewOverlay()
50 if overlay == nil {
51 _ = bridge.Destroy()
52 return nil
53 }
54 overlay.SetChild(mainWidget)
55 popupWidget.SetVisible(false)
56 popupWidget.SetHalign(gtk.AlignStartValue)
57 popupWidget.SetValign(gtk.AlignStartValue)
58 popupWidget.SetHexpand(false)
59 popupWidget.SetVexpand(false)
60 popupWidget.SetCanTarget(false)
61 popupWidget.SetCanFocus(false)
62 popupWidget.SetFocusable(false)
63 overlay.AddOverlay(popupWidget)
64 overlay.SetClipOverlay(popupWidget, true)
65 overlay.SetMeasureOverlay(popupWidget, false)
66 root := &overlay.Widget
67 root.SetHexpand(true)
68 root.SetVexpand(true)
69 root.SetCanFocus(true)
70 root.SetFocusable(true)
71 root.SetFocusOnClick(true)
72 return &popupBridgeSurface{
73 ctx: ctx,
74 root: root,
75 mainWidget: mainWidget,
76 bridge: bridge,
77 popupWidget: popupWidget,
78 }
79}
80
81func (s *popupBridgeSurface) RootWidget() *gtk.Widget {
82 if s == nil {
83 return nil
84 }
85 return s.root
86}
87
88func (s *popupBridgeSurface) RenderHandler(hooks cef2gtk.Hooks) purecef.RenderHandler {
89 if s == nil || s.bridge == nil {
90 return nil
91 }
92 return s.bridge.RenderHandler(hooks)
93}
94
95func (s *popupBridgeSurface) PrepareOnGTKThread() error {
96 if s == nil || s.bridge == nil {
97 return nil
98 }
99 if !s.prepared.CompareAndSwap(0, 1) {
100 return nil
101 }
102 if err := s.bridge.PrepareOnGTKThread(); err != nil {
103 s.prepared.Store(0)
104 return err
105 }
106 return nil
107}
108
109func (s *popupBridgeSurface) SetPopupVisible(visible bool) {
110 if s == nil || s.popupWidget == nil {
111 return
112 }
113 if visible {
114 if err := s.PrepareOnGTKThread(); err != nil {
115 logging.FromContext(popupSurfaceLogContext(s.ctx)).Error().
116 Err(err).
117 Msg("cef: popupBridgeSurface.SetPopupVisible failed to PrepareOnGTKThread")
118 return
119 }
120 }
121 s.popupWidget.SetVisible(visible)
122 if s.root != nil {
123 s.root.QueueAllocate()
124 }
125}
126
127func (s *popupBridgeSurface) SetPopupRect(rect purecef.Rect) {
128 if s == nil || s.popupWidget == nil {
129 return
130 }
131 if rect.Width <= 0 || rect.Height <= 0 {
132 s.popupWidget.SetVisible(false)
133 return
134 }
135 s.popupWidget.SetMarginStart(int(rect.X))
136 s.popupWidget.SetMarginTop(int(rect.Y))
137 s.popupWidget.SetSizeRequest(int(rect.Width), int(rect.Height))
138 s.popupWidget.QueueResize()
139 if s.root != nil {
140 s.root.QueueResize()
141 }
142}
143
144func popupSurfaceLogContext(ctx context.Context) context.Context {
145 if ctx != nil {
146 return ctx
147 }
148 return context.Background()
149}
150
151func (s *popupBridgeSurface) DestroyOnGTKThread() {
152 if s == nil || s.bridge == nil {
153 return
154 }
155 _ = s.bridge.Destroy()
156 s.bridge = nil
157 s.popupWidget = nil
158 s.mainWidget = nil
159 s.root = nil
160 s.prepared.Store(0)
161}