Skip to content

Commit 50db9c2

Browse files
committed
Added support of window actions
1 parent d427007 commit 50db9c2

File tree

4 files changed

+203
-3
lines changed

4 files changed

+203
-3
lines changed

include/lsp-plug.in/tk/sys/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace lsp
5353
SLOT_MOUSE_POINTER, //!< SLOT_MOUSE_POINTER called to resolve the current mouse pointer for the widget
5454
SLOT_SHOW, //!< SLOT_SHOW Triggered when widget becomes visible
5555
SLOT_HIDE, //!< SLOT_HIDE Triggered when widget becomes invisible
56+
SLOT_STATE, //!< SLOT_STATE Triggered when window state is changed
5657
SLOT_BEGIN_EDIT, //!< SLOG_BEGIN_EDIT Triggered when the possible durable editing has started (for example, mouse click + drag)
5758
SLOT_END_EDIT, //!< SLOG_END_EDIT Triggered when the possible durable editing has finished (for example, mouse click + drag)
5859
SLOT_SUBMIT, //!< SLOT_SUBMIT Triggered when value(s) stored by the widget is submitted (but can be not changed)

include/lsp-plug.in/tk/widgets/containers/Window.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace lsp
4343
prop::Integer sBorderSize;
4444
prop::Float sBorderRadius;
4545
prop::WindowActions sActions;
46+
prop::WindowState sWindowState;
4647
prop::Position sPosition;
4748
prop::Size sWindowSize;
4849
prop::SizeConstraints sConstraints;
@@ -114,6 +115,7 @@ namespace lsp
114115
prop::Integer sBorderSize;
115116
prop::Float sBorderRadius;
116117
prop::WindowActions sActions;
118+
prop::WindowState sWindowState;
117119
prop::Position sPosition;
118120
prop::Size sWindowSize;
119121
prop::SizeConstraints sSizeConstraints;
@@ -131,6 +133,7 @@ namespace lsp
131133
protected:
132134
static status_t tmr_redraw_request(ws::timestamp_t sched, ws::timestamp_t ts, void *args);
133135
static status_t slot_window_close(Widget *sender, void *ptr, void *data);
136+
static status_t slot_window_state(Widget *sender, void *ptr, void *data);
134137

135138
static void on_add_item(void *obj, Property *prop, void *w);
136139
static void on_remove_item(void *obj, Property *prop, void *w);
@@ -238,6 +241,7 @@ namespace lsp
238241
LSP_TK_PROPERTY(BorderStyle, border_style, &sBorderStyle)
239242
LSP_TK_PROPERTY(Integer, border_size, &sBorderSize)
240243
LSP_TK_PROPERTY(WindowActions, actions, &sActions)
244+
LSP_TK_PROPERTY(WindowState, state, &sWindowState)
241245
LSP_TK_PROPERTY(Size, size, &sWindowSize)
242246
LSP_TK_PROPERTY(SizeConstraints, constraints, &sSizeConstraints)
243247
LSP_TK_PROPERTY(Layout, layout, &sLayout)
@@ -300,6 +304,13 @@ namespace lsp
300304
*/
301305
virtual status_t on_close(const ws::event_t *e);
302306

307+
/** State change event
308+
*
309+
* @param e close event
310+
* @return status of operation
311+
*/
312+
virtual status_t on_window_state(const ws::event_t *e);
313+
303314
/** Set window icon
304315
*
305316
* @param bgra color data

src/main/widgets/containers/Window.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace lsp
3838
sBorderSize.bind("border.size", this);
3939
sBorderRadius.bind("border.radius", this);
4040
sActions.bind("actions", this);
41+
sWindowState.bind("state", this);
4142
sPosition.bind("position", this);
4243
sWindowSize.bind("size", this);
4344
sConstraints.bind("size.constraints", this);
@@ -49,6 +50,7 @@ namespace lsp
4950
sBorderSize.set(0);
5051
sBorderRadius.set(2);
5152
sActions.set_actions(ws::WA_ALL);
53+
sWindowState.set_normal();
5254
sPosition.set(0, 0);
5355
sWindowSize.set(160, 100);
5456
sConstraints.set(-1, -1, -1, -1);
@@ -75,6 +77,7 @@ namespace lsp
7577
sBorderSize(&sProperties),
7678
sBorderRadius(&sProperties),
7779
sActions(&sProperties),
80+
sWindowState(&sProperties),
7881
sPosition(&sProperties),
7982
sWindowSize(&sProperties),
8083
sSizeConstraints(&sProperties),
@@ -146,6 +149,7 @@ namespace lsp
146149
sBorderSize.bind("border.size", &sStyle);
147150
sBorderRadius.bind("border.radius", &sStyle);
148151
sActions.bind("actions", &sStyle);
152+
sWindowState.bind("state", &sStyle);
149153
sPosition.bind("position", &sStyle);
150154
sWindowSize.bind("size", &sStyle);
151155
sSizeConstraints.bind("size.constraints", &sStyle);
@@ -158,8 +162,9 @@ namespace lsp
158162
// Add slot(s)
159163
handler_id_t id = 0;
160164
id = sSlots.add(SLOT_CLOSE, slot_window_close, self());
161-
if (id < 0)
162-
return - id;
165+
if (id < 0) return -id;
166+
id = sSlots.add(SLOT_STATE, slot_window_state, self());
167+
if (id < 0) return -id;
163168

164169
// Set self event handler
165170
if (pWindow != NULL)
@@ -323,6 +328,15 @@ namespace lsp
323328
return (_this != NULL) ? _this->on_close(static_cast<ws::event_t *>(data)) : STATUS_BAD_ARGUMENTS;
324329
}
325330

331+
status_t Window::slot_window_state(Widget *sender, void *ptr, void *data)
332+
{
333+
if ((ptr == NULL) || (data == NULL))
334+
return STATUS_BAD_ARGUMENTS;
335+
336+
Window *_this = widget_ptrcast<Window>(ptr);
337+
return (_this != NULL) ? _this->on_window_state(static_cast<ws::event_t *>(data)) : STATUS_BAD_ARGUMENTS;
338+
}
339+
326340
void Window::on_add_item(void *obj, Property *prop, void *w)
327341
{
328342
Widget *widget = widget_ptrcast<Widget>(w);
@@ -633,10 +647,12 @@ namespace lsp
633647
pWindow->set_border_style(sBorderStyle.get());
634648
if (sActions.is(prop))
635649
pWindow->set_window_actions(sActions.actions());
650+
if (sWindowState.is(prop))
651+
pWindow->set_window_state(sWindowState.get());
636652
if (sPosition.is(prop))
637653
pWindow->move(sPosition.left(), sPosition.top());
638654

639-
if (prop->one_of(sSizeConstraints, sScaling, sActions, sFontScaling, sWindowSize))
655+
if (prop->one_of(sSizeConstraints, sScaling, sActions, sWindowState, sFontScaling, sWindowSize))
640656
{
641657
// float scaling = lsp_max(0.0f, sScaling.get());
642658
//
@@ -930,6 +946,14 @@ namespace lsp
930946
sVisibility.commit_value(false);
931947
break;
932948

949+
case ws::UIE_STATE:
950+
if (sWindowState.get() == e->nCode)
951+
break;
952+
953+
sWindowState.commit_value(ws::window_state_t(e->nCode));
954+
sSlots.execute(SLOT_STATE, this, &ev);
955+
break;
956+
933957
case ws::UIE_REDRAW:
934958
query_draw(REDRAW_SURFACE);
935959
break;
@@ -1381,6 +1405,11 @@ namespace lsp
13811405
return STATUS_OK;
13821406
}
13831407

1408+
status_t Window::on_window_state(const ws::event_t *e)
1409+
{
1410+
return STATUS_OK;
1411+
}
1412+
13841413
void Window::realize(const ws::rectangle_t *r)
13851414
{
13861415
// lsp_trace("width=%d, height=%d", int(r->nWidth), int(r->nHeight));

src/test/mtest/sys/win_actions.cpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright (C) 2025 Linux Studio Plugins Project <https://lsp-plug.in/>
3+
* (C) 2025 Vladimir Sadovnikov <[email protected]>
4+
*
5+
* This file is part of lsp-tk-lib
6+
* Created on: 5 мая 2020 г.
7+
*
8+
* lsp-tk-lib is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* any later version.
12+
*
13+
* lsp-tk-lib is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with lsp-tk-lib. If not, see <https://www.gnu.org/licenses/>.
20+
*/
21+
22+
#include <lsp-plug.in/test-fw/mtest.h>
23+
#include <lsp-plug.in/tk/tk.h>
24+
25+
MTEST_BEGIN("tk.sys", win_actions)
26+
27+
static status_t slot_close(tk::Widget *sender, void *ptr, void *data)
28+
{
29+
sender->display()->quit_main();
30+
return STATUS_OK;
31+
}
32+
33+
static status_t slot_key_up(tk::Widget *sender, void *ptr, void *data)
34+
{
35+
tk::Window *wnd = tk::widget_cast<tk::Window>(sender);
36+
ws::event_t *ev = static_cast<ws::event_t *>(data);
37+
test_type_t *_this = static_cast<test_type_t *>(ptr);
38+
39+
if ((wnd != NULL) && (ev != NULL) && (ev->nType == ws::UIE_KEY_UP))
40+
{
41+
_this->printf("Key up: %c (0x%x)\n", (char)ev->nCode, int(ev->nCode));
42+
43+
if ((ev->nCode == '+') || (ev->nCode == ws::WSK_KEYPAD_ADD))
44+
wnd->style()->schema()->scaling()->add(0.25f);
45+
else if ((ev->nCode == '-') || (ev->nCode == ws::WSK_KEYPAD_SUBTRACT))
46+
wnd->style()->schema()->scaling()->sub(0.25f);
47+
}
48+
return STATUS_OK;
49+
}
50+
51+
static status_t slot_state(tk::Widget *sender, void *ptr, void *data)
52+
{
53+
tk::Window *wnd = tk::widget_cast<tk::Window>(sender);
54+
test_type_t *_this = static_cast<test_type_t *>(ptr);
55+
56+
_this->printf("Window state is now: %d\n", int(wnd->state()->get()));
57+
return STATUS_OK;
58+
}
59+
60+
static status_t slot_minimize(tk::Widget *sender, void *ptr, void *data)
61+
{
62+
tk::Window *wnd = static_cast<tk::Window *>(ptr);
63+
wnd->state()->set_minimized();
64+
return STATUS_OK;
65+
}
66+
67+
static status_t slot_maximize(tk::Widget *sender, void *ptr, void *data)
68+
{
69+
tk::Window *wnd = static_cast<tk::Window *>(ptr);
70+
wnd->state()->set_maximized();
71+
return STATUS_OK;
72+
}
73+
74+
static status_t slot_restore(tk::Widget *sender, void *ptr, void *data)
75+
{
76+
tk::Window *wnd = static_cast<tk::Window *>(ptr);
77+
wnd->state()->set_normal();
78+
return STATUS_OK;
79+
}
80+
81+
MTEST_MAIN
82+
{
83+
tk::Display *dpy = new tk::Display();
84+
MTEST_ASSERT(dpy != NULL);
85+
lsp_finally { delete dpy; };
86+
87+
MTEST_ASSERT(dpy->init(0, NULL) == STATUS_OK);
88+
89+
// Create widgets
90+
tk::Window *wnd = new tk::Window(dpy);
91+
lsp_finally {
92+
wnd->destroy();
93+
delete wnd;
94+
};
95+
tk::Box *box = new tk::Box(dpy);
96+
lsp_finally {
97+
box->destroy();
98+
delete box;
99+
};
100+
tk::Button *minimize = new tk::Button(dpy);
101+
lsp_finally {
102+
minimize->destroy();
103+
delete minimize;
104+
};
105+
tk::Button *maximize = new tk::Button(dpy);
106+
lsp_finally {
107+
maximize->destroy();
108+
delete maximize;
109+
};
110+
tk::Button *restore = new tk::Button(dpy);
111+
lsp_finally {
112+
restore->destroy();
113+
delete restore;
114+
};
115+
116+
117+
// Initialize window
118+
MTEST_ASSERT(wnd->init() == STATUS_OK);
119+
MTEST_ASSERT(wnd->title()->set_raw("Test window") == STATUS_OK);
120+
MTEST_ASSERT(wnd->role()->set_raw("test") == STATUS_OK);
121+
wnd->bg_color()->set_rgb(0, 0.75, 1.0);
122+
wnd->actions()->set_actions(ws::WA_MOVE | ws::WA_RESIZE | ws::WA_CLOSE | ws::WA_MINIMIZE | ws::WA_MAXIMIZE);
123+
wnd->border_style()->set(ws::BS_SINGLE);
124+
wnd->constraints()->set(160, 100, 640, 400);
125+
wnd->size()->set(320, 200);
126+
wnd->slot(tk::SLOT_CLOSE)->bind(slot_close, this);
127+
wnd->slot(tk::SLOT_KEY_UP)->bind(slot_key_up, this);
128+
wnd->slot(tk::SLOT_STATE)->bind(slot_state, this);
129+
wnd->layout()->set(-0.5, 0.5, 0.5, 0.5);
130+
131+
// Initialize void widget
132+
MTEST_ASSERT(box->init() == STATUS_OK);
133+
box->orientation()->set_horizontal();
134+
MTEST_ASSERT(wnd->add(box) == STATUS_OK);
135+
136+
MTEST_ASSERT(minimize->init() == STATUS_OK);
137+
minimize->text()->set_raw("Minimize");
138+
minimize->slot(tk::SLOT_SUBMIT)->bind(slot_minimize, wnd);
139+
MTEST_ASSERT(box->add(minimize) == STATUS_OK);
140+
141+
MTEST_ASSERT(maximize->init() == STATUS_OK);
142+
maximize->text()->set_raw("Maximize");
143+
maximize->slot(tk::SLOT_SUBMIT)->bind(slot_maximize, wnd);
144+
MTEST_ASSERT(box->add(maximize) == STATUS_OK);
145+
146+
MTEST_ASSERT(restore->init() == STATUS_OK);
147+
restore->text()->set_raw("Restore");
148+
restore->slot(tk::SLOT_SUBMIT)->bind(slot_restore, wnd);
149+
MTEST_ASSERT(box->add(restore) == STATUS_OK);
150+
151+
// Show window
152+
wnd->visibility()->set(true);
153+
154+
MTEST_ASSERT(dpy->main() == STATUS_OK);
155+
}
156+
157+
MTEST_END
158+
159+

0 commit comments

Comments
 (0)