1
|
#include <CtrlCore/CtrlCore.h>
|
2
|
|
3
|
#ifdef GUI_GTK
|
4
|
|
5
|
NAMESPACE_UPP
|
6
|
|
7
|
#define LLOG(x)
|
8
|
|
9
|
Rect Ctrl::frameMargins;
|
10
|
|
11
|
Rect Ctrl::GetFrameMargins()
|
12
|
{
|
13
|
GuiLock __;
|
14
|
return frameMargins != Rect(0, 0, 0, 0) ? frameMargins : Rect(8, 32, 8, 8);
|
15
|
}
|
16
|
|
17
|
void TopWindow::SyncSizeHints()
|
18
|
{
|
19
|
GuiLock __;
|
20
|
if(!top)
|
21
|
return;
|
22
|
GdkGeometry m;
|
23
|
Size sz0 = GetRect().GetSize();
|
24
|
Size sz = sz0;
|
25
|
if(sizeable)
|
26
|
sz = GetMinSize();
|
27
|
m.min_width = sz.cx;
|
28
|
m.min_height = sz.cy;
|
29
|
sz = sz0;
|
30
|
if(sizeable)
|
31
|
sz = GetMaxSize();
|
32
|
m.max_width = sz.cx;
|
33
|
m.max_height = sz.cy;
|
34
|
gtk_window_set_resizable(gtk(), sizeable);
|
35
|
gtk_window_set_geometry_hints(gtk(), top->window, &m,
|
36
|
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
|
37
|
}
|
38
|
|
39
|
void TopWindow::SyncTitle()
|
40
|
{
|
41
|
GuiLock __;
|
42
|
if(top)
|
43
|
gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8));
|
44
|
}
|
45
|
|
46
|
void TopWindow::SyncCaption()
|
47
|
{
|
48
|
GuiLock __;
|
49
|
SyncTitle();
|
50
|
if(top) {
|
51
|
GList *icons = NULL;
|
52
|
if(gdk_icon.Set(icon))
|
53
|
icons = g_list_append(icons, gdk_icon);
|
54
|
if(gdk_largeicon.Set(largeicon))
|
55
|
icons = g_list_append(icons, gdk_largeicon);
|
56
|
if(icons != NULL) {
|
57
|
gtk_window_set_icon_list(gtk(), icons);
|
58
|
g_list_free(icons);
|
59
|
}
|
60
|
gtk_window_set_decorated(gtk(), !frameless);
|
61
|
gtk_window_set_urgency_hint(gtk(), urgent);
|
62
|
}
|
63
|
}
|
64
|
|
65
|
void TopWindow::CenterRect(Ctrl *owner)
|
66
|
{
|
67
|
GuiLock __;
|
68
|
SetupRect();
|
69
|
if(owner && center == 1 || center == 2) {
|
70
|
Size sz = GetRect().Size();
|
71
|
Rect r, wr;
|
72
|
wr = Ctrl::GetWorkArea();
|
73
|
Rect fm = GetFrameMargins();
|
74
|
if(center == 1)
|
75
|
r = owner->GetRect();
|
76
|
else
|
77
|
r = wr;
|
78
|
Point p = r.CenterPos(sz);
|
79
|
r = RectC(p.x, p.y, sz.cx, sz.cy);
|
80
|
wr.left += fm.left;
|
81
|
wr.right -= fm.right;
|
82
|
wr.top += fm.top;
|
83
|
wr.bottom -= fm.bottom;
|
84
|
if(r.top < wr.top) {
|
85
|
r.bottom += wr.top - r.top;
|
86
|
r.top = wr.top;
|
87
|
}
|
88
|
if(r.bottom > wr.bottom)
|
89
|
r.bottom = wr.bottom;
|
90
|
minsize.cx = min(minsize.cx, r.GetWidth());
|
91
|
minsize.cy = min(minsize.cy, r.GetHeight());
|
92
|
SetRect(r);
|
93
|
}
|
94
|
}
|
95
|
|
96
|
gboolean TopWindow::StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
|
97
|
{
|
98
|
TopWindow *w = (TopWindow *)user_data;
|
99
|
dword h = event->new_window_state;
|
100
|
if(h & GDK_WINDOW_STATE_FULLSCREEN)
|
101
|
w->state = FULLSCREEN;
|
102
|
else
|
103
|
if(h & GDK_WINDOW_STATE_ICONIFIED)
|
104
|
w->state = MINIMIZED;
|
105
|
else
|
106
|
if(h & GDK_WINDOW_STATE_MAXIMIZED)
|
107
|
w->state = MAXIMIZED;
|
108
|
else
|
109
|
w->state = OVERLAPPED;
|
110
|
w->topmost = h & GDK_WINDOW_STATE_ABOVE;
|
111
|
return FALSE;
|
112
|
}
|
113
|
|
114
|
void TopWindow::Open(Ctrl *owner)
|
115
|
{
|
116
|
GuiLock __;
|
117
|
LLOG("OPEN " << Name() << " owner: " << UPP::Name(owner));
|
118
|
if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1))
|
119
|
DistributeAccessKeys();
|
120
|
if(fullscreen)
|
121
|
SetRect(GetPrimaryScreenArea());
|
122
|
else
|
123
|
CenterRect(owner);
|
124
|
IgnoreMouseUp();
|
125
|
Create(owner, false);
|
126
|
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this);
|
127
|
SyncSizeHints();
|
128
|
SyncCaption();
|
129
|
PlaceFocus();
|
130
|
int q = state;
|
131
|
state = OVERLAPPED;
|
132
|
SetMode(q);
|
133
|
SyncTopMost();
|
134
|
GdkRectangle fr;
|
135
|
gdk_window_get_frame_extents(gdk(), &fr);
|
136
|
Rect r = GetRect();
|
137
|
frameMargins.left = max(frameMargins.left, minmax(r.left - fr.x, 0, 32));
|
138
|
frameMargins.right = max(frameMargins.right, minmax(fr.x + fr.width - r.right, 0, 32));
|
139
|
frameMargins.top = max(frameMargins.top, minmax(r.top - fr.y, 0, 64));
|
140
|
frameMargins.bottom = max(frameMargins.bottom, minmax(fr.y + fr.height - r.bottom, 0, 48));
|
141
|
}
|
142
|
|
143
|
void TopWindow::Open()
|
144
|
{
|
145
|
Open(GetActiveWindow());
|
146
|
}
|
147
|
|
148
|
void TopWindow::OpenMain()
|
149
|
{
|
150
|
Open(NULL);
|
151
|
}
|
152
|
|
153
|
void TopWindow::SyncTopMost()
|
154
|
{
|
155
|
GuiLock __;
|
156
|
if(top)
|
157
|
gtk_window_set_keep_above(gtk(), topmost);
|
158
|
}
|
159
|
|
160
|
void TopWindow::SetMode(int mode)
|
161
|
{
|
162
|
GuiLock __;
|
163
|
GtkWindow *w = gtk();
|
164
|
if(w)
|
165
|
switch(state) {
|
166
|
case MINIMIZED:
|
167
|
gtk_window_deiconify(w);
|
168
|
break;
|
169
|
case MAXIMIZED:
|
170
|
gtk_window_unmaximize(w);
|
171
|
break;
|
172
|
case FULLSCREEN:
|
173
|
gtk_window_unfullscreen(w);
|
174
|
break;
|
175
|
}
|
176
|
state = mode;
|
177
|
if(w)
|
178
|
switch(state) {
|
179
|
case MINIMIZED:
|
180
|
gtk_window_iconify(w);
|
181
|
break;
|
182
|
case MAXIMIZED:
|
183
|
gtk_window_maximize(w);
|
184
|
break;
|
185
|
case FULLSCREEN:
|
186
|
gtk_window_fullscreen(w);
|
187
|
break;
|
188
|
}
|
189
|
}
|
190
|
|
191
|
void TopWindow::Minimize(bool effect)
|
192
|
{
|
193
|
SetMode(MINIMIZED);
|
194
|
}
|
195
|
|
196
|
TopWindow& TopWindow::FullScreen(bool b)
|
197
|
{
|
198
|
SetMode(FULLSCREEN);
|
199
|
return *this;
|
200
|
}
|
201
|
|
202
|
void TopWindow::Maximize(bool effect)
|
203
|
{
|
204
|
SetMode(MAXIMIZED);
|
205
|
}
|
206
|
|
207
|
void TopWindow::Overlap(bool effect)
|
208
|
{
|
209
|
SetMode(OVERLAPPED);
|
210
|
}
|
211
|
|
212
|
TopWindow& TopWindow::TopMost(bool b, bool)
|
213
|
{
|
214
|
GuiLock __;
|
215
|
topmost = b;
|
216
|
SyncTopMost();
|
217
|
return *this;
|
218
|
}
|
219
|
|
220
|
bool TopWindow::IsTopMost() const
|
221
|
{
|
222
|
GuiLock __;
|
223
|
return topmost;
|
224
|
}
|
225
|
|
226
|
void TopWindow::GuiPlatformConstruct()
|
227
|
{
|
228
|
topmost = false;
|
229
|
}
|
230
|
|
231
|
void TopWindow::GuiPlatformDestruct()
|
232
|
{
|
233
|
}
|
234
|
|
235
|
void TopWindow::SerializePlacement(Stream& s, bool reminimize)
|
236
|
{
|
237
|
GuiLock __;
|
238
|
int version = 0;
|
239
|
s / version;
|
240
|
Rect rect = GetRect();
|
241
|
s % overlapped % rect;
|
242
|
bool mn = state == MINIMIZED;
|
243
|
bool mx = state == MAXIMIZED;
|
244
|
s.Pack(mn, mx);
|
245
|
LLOG("TopWindow::SerializePlacement / " << (s.IsStoring() ? "write" : "read"));
|
246
|
LLOG("minimized = " << mn << ", maximized = " << mx);
|
247
|
LLOG("rect = " << rect << ", overlapped = " << overlapped);
|
248
|
if(s.IsLoading()) {
|
249
|
if(mn) rect = overlapped;
|
250
|
Rect limit = GetVirtualWorkArea();
|
251
|
Rect fm = GetFrameMargins();
|
252
|
limit.left += fm.left;
|
253
|
limit.right -= fm.right;
|
254
|
limit.top += fm.top;
|
255
|
limit.bottom -= fm.bottom;
|
256
|
Size sz = min(rect.Size(), limit.Size());
|
257
|
rect = RectC(
|
258
|
minmax(rect.left, limit.left, limit.right - sz.cx),
|
259
|
minmax(rect.top, limit.top, limit.bottom - sz.cy),
|
260
|
sz.cx, sz.cy);
|
261
|
state = OVERLAPPED;
|
262
|
if(mn && reminimize)
|
263
|
state = MINIMIZED;
|
264
|
if(mx)
|
265
|
state = MAXIMIZED;
|
266
|
if(state == OVERLAPPED)
|
267
|
SetRect(rect);
|
268
|
if(IsOpen()) {
|
269
|
if(state == MINIMIZED)
|
270
|
Minimize(false);
|
271
|
if(state == MAXIMIZED)
|
272
|
Maximize(false);
|
273
|
}
|
274
|
}
|
275
|
}
|
276
|
|
277
|
END_UPP_NAMESPACE
|
278
|
|
279
|
#endif
|