erythros/Applications/OS/TaskSwitcher.app/Run.HC

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;