198 lines
No EOL
6.9 KiB
HolyC
198 lines
No EOL
6.9 KiB
HolyC
Gui.App();
|
|
#define MAX_THUMBS_PER_LINE 10
|
|
|
|
Window* win = Compositor.CreateWindow(120, 120, 640, 192, WIN_FLAGS_SKIP);
|
|
Window* to_be_focused_win = NULL;
|
|
Bool task_switcher_active = FALSE;
|
|
Bool task_switcher_invoke = FALSE;
|
|
|
|
I64 caption_width = 0;
|
|
F64 win_scale = 0.0;
|
|
I64 win_thumb_size = 128;
|
|
I64 win_thumb_container_size = win_thumb_size + 32;
|
|
I64 win_index = -1;
|
|
I64 win_items = 0;
|
|
I64 cur_index = 0;
|
|
U8* cur_win_title = NULL;
|
|
Context2D* win_scaled = NULL;
|
|
|
|
@compositor_windows_list* win_list = NULL;
|
|
|
|
TextLabelWidget* caption = Gui.CreateWidget(win, WIDGET_TYPE_LABEL, 8, 8, 256, 64);
|
|
Gui.Widget.SetFont(caption, "Eight Bit Dragon");
|
|
|
|
Context2DWidget* cursor = NULL;
|
|
|
|
U0 keypress_callback(Window* win, I64)
|
|
{
|
|
I64 i;
|
|
if (!task_switcher_active) {
|
|
if ((KeyDown(SC_CTRL) && KeyDown(Char2ScanCode('w'))) || (KeyDown(SC_ALT) && KeyDown(SC_F4)))
|
|
if (Compositor.active_win != win && Compositor.active_win->callback.close)
|
|
Compositor.active_win->callback.close(Compositor.active_win);
|
|
return;
|
|
}
|
|
if (KeyDown(SC_TAB)) {
|
|
if (KeyDown(SC_SHIFT))
|
|
win_index--;
|
|
else
|
|
win_index += T(win_items > 1 && task_switcher_invoke, 2, 1);
|
|
}
|
|
|
|
if (!win_items)
|
|
return;
|
|
|
|
@window_widgets_list* set_item = win->widget->next->next->next;
|
|
if (win_index < 0)
|
|
win_index = win_items - 1;
|
|
if (win_index >= win_items)
|
|
win_index = 0;
|
|
for (i = 0; i < win_index; i++)
|
|
set_item = set_item->next;
|
|
|
|
cursor->x = set_item->widget->x;
|
|
cursor->y = set_item->widget->y;
|
|
|
|
to_be_focused_win = set_item->widget->id;
|
|
Gui.Widget.SetText(caption, set_item->widget->tag);
|
|
caption->width = Print2D(NULL, Compositor.theme.font.menu, 0, 0, , , &caption->text);
|
|
caption->x = (win->width / 2) - (caption->width / 2);
|
|
caption->y = win->height - 24;
|
|
|
|
Gui.Window.Refresh(win);
|
|
task_switcher_invoke = FALSE;
|
|
}
|
|
|
|
U0 @taskswitcher_clear_win_thumbs(Window* win)
|
|
{
|
|
@window_widgets_list* iter_widget = win->widget;
|
|
@window_widgets_list* del_widget = NULL;
|
|
while (iter_widget->next)
|
|
iter_widget = iter_widget->next;
|
|
while (iter_widget->widget->type == WIDGET_TYPE_CONTEXT2D) {
|
|
iter_widget = iter_widget->prev;
|
|
del_widget = iter_widget->next;
|
|
iter_widget->next = NULL;
|
|
if (del_widget->widget(Context2DWidget*)->ctx)
|
|
DelContext2D(del_widget->widget(Context2DWidget*)->ctx);
|
|
Free(del_widget->widget->tag);
|
|
Free(del_widget->widget);
|
|
Free(del_widget);
|
|
}
|
|
Gui.Widget.SetText(caption, "");
|
|
}
|
|
|
|
U0 @taskswitcher_render_win_thumbs(Window* win)
|
|
{
|
|
@compositor_windows_list* origin_list;
|
|
@compositor_windows_list* iter_list;
|
|
Context2DWidget* widget = NULL;
|
|
cursor = Gui.CreateWidget(win, WIDGET_TYPE_CONTEXT2D, -999, -999,
|
|
win_thumb_container_size, win_thumb_container_size);
|
|
cursor->ctx = NewContext2D(win_thumb_container_size, win_thumb_container_size);
|
|
cursor->ctx->fill(Compositor.theme.color.hilight);
|
|
|
|
I64 min_caption_width = 0;
|
|
win_items = 0;
|
|
I64 cur_item = 0;
|
|
I64 item_offset = 0;
|
|
|
|
origin_list = Compositor.windows->next;
|
|
while (origin_list->next)
|
|
origin_list = origin_list->next;
|
|
|
|
iter_list = origin_list;
|
|
while (iter_list) {
|
|
if (iter_list->window)
|
|
if (!@gui_window_flag_is_set(iter_list->window, WIN_FLAGS_SKIP)) {
|
|
min_caption_width = Max(min_caption_width,
|
|
Print2D(NULL, Compositor.theme.font.menu, 0, 0, , ,
|
|
"%s - [%dx%d] at [%d, %d]", iter_list->window->title,
|
|
iter_list->window->width, iter_list->window->height,
|
|
iter_list->window->x, iter_list->window->y));
|
|
win_items++;
|
|
}
|
|
iter_list = iter_list->prev;
|
|
}
|
|
|
|
win->width = Max((win_thumb_container_size * win_items) + T(win_items, 4, 0),
|
|
64 + min_caption_width);
|
|
|
|
item_offset = (win->width / 2) - (((win_thumb_container_size * win_items) + T(win_items, 0, 0)) / 2);
|
|
|
|
iter_list = origin_list;
|
|
while (iter_list) {
|
|
if (iter_list->window)
|
|
if (!@gui_window_flag_is_set(iter_list->window, WIN_FLAGS_SKIP)) {
|
|
widget = Gui.CreateWidget(
|
|
win, WIDGET_TYPE_CONTEXT2D,
|
|
(win_thumb_container_size * cur_item) + item_offset, 0,
|
|
win_thumb_container_size, win_thumb_container_size);
|
|
widget->ctx = NewContext2D(win_thumb_container_size, win_thumb_container_size);
|
|
widget->ctx->fill(0);
|
|
win_scale = 1.0;
|
|
while (iter_list->window->backing_store->width * win_scale > win_thumb_size || iter_list->window->backing_store->height * win_scale > win_thumb_size)
|
|
win_scale -= 0.001;
|
|
|
|
win_scaled = Scale2D(iter_list->window->backing_store, win_scale, win_scale);
|
|
widget->ctx->fill(0);
|
|
widget->ctx->blot(
|
|
(win_thumb_container_size / 2) - (win_scaled->width / 2),
|
|
(win_thumb_container_size / 2) - (win_scaled->height / 2),
|
|
win_scaled);
|
|
DelContext2D(win_scaled);
|
|
widget->tag = CAlloc(256);
|
|
StrPrint(widget->tag, "%s - [%dx%d] at [%d, %d]",
|
|
iter_list->window->title, iter_list->window->width,
|
|
iter_list->window->height, iter_list->window->x,
|
|
iter_list->window->y);
|
|
widget->id = iter_list->window; // FIXME: We are abusing this property,
|
|
// introduce a better way to do this
|
|
|
|
cur_item++;
|
|
}
|
|
iter_list = iter_list->prev;
|
|
}
|
|
}
|
|
|
|
U0 Main()
|
|
{
|
|
Gui.Window.SetTitle(win, "TaskSwitcher");
|
|
Gui.Window.EnableAlphaChannel(win);
|
|
Gui.Window.SetOpacity(win, 224);
|
|
Compositor.RegisterForGlobalInputEvents(win);
|
|
Gui.Window.SetCallback(win, "keypress", &keypress_callback);
|
|
Gui.Window.Hide(win);
|
|
|
|
while (1) {
|
|
if (KeyDown(SC_ALT) && KeyDown(SC_TAB))
|
|
task_switcher_active = TRUE;
|
|
if (!KeyDown(SC_ALT))
|
|
task_switcher_active = FALSE;
|
|
switch (task_switcher_active) {
|
|
case TRUE:
|
|
if (!to_be_focused_win) {
|
|
to_be_focused_win = Compositor.active_win;
|
|
task_switcher_invoke = TRUE;
|
|
@taskswitcher_render_win_thumbs(win);
|
|
Gui.Window.Center(win);
|
|
Gui.Window.SetFocus(win);
|
|
Gui.Window.Show(win);
|
|
}
|
|
break;
|
|
case FALSE:
|
|
if (to_be_focused_win) {
|
|
Gui.Window.SetFocus(to_be_focused_win);
|
|
Gui.Window.Show(to_be_focused_win);
|
|
to_be_focused_win = NULL;
|
|
Gui.Window.Hide(win);
|
|
@taskswitcher_clear_win_thumbs(win);
|
|
win_index = -1;
|
|
}
|
|
break;
|
|
}
|
|
Sleep(1);
|
|
}
|
|
}
|
|
|
|
Main; |