2018-08-14 11:24:25 +03:00
|
|
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
|
|
* This file is part of ToaruOS and is released under the terms
|
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
|
|
* Copyright (C) 2016-2018 K. Lange
|
|
|
|
*
|
|
|
|
* The default "fancy" decorations theme.
|
|
|
|
*
|
|
|
|
* Based on an old gtk-window-decorator theme I used to use many,
|
|
|
|
* many years ago.
|
|
|
|
*/
|
2018-02-25 15:54:39 +03:00
|
|
|
#include <stdint.h>
|
2018-09-24 09:06:42 +03:00
|
|
|
#include <dlfcn.h>
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2018-03-19 05:38:11 +03:00
|
|
|
#include <toaru/yutani.h>
|
|
|
|
#include <toaru/graphics.h>
|
|
|
|
#include <toaru/decorations.h>
|
2021-07-05 16:50:25 +03:00
|
|
|
#include <toaru/text.h>
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2018-04-21 12:57:42 +03:00
|
|
|
#define INACTIVE 10
|
2018-02-25 15:54:39 +03:00
|
|
|
|
|
|
|
#define TTK_FANCY_PATH "/usr/share/ttk/"
|
|
|
|
|
|
|
|
static int u_height = 33;
|
|
|
|
static int ul_width = 10;
|
|
|
|
static int ur_width = 10;
|
|
|
|
static int mr_width = 6;
|
|
|
|
static int l_height = 9;
|
|
|
|
static int ll_width = 9;
|
|
|
|
static int lr_width = 9;
|
2021-07-05 16:50:25 +03:00
|
|
|
static struct TT_Font * _tt_font = NULL;
|
2018-02-25 15:54:39 +03:00
|
|
|
|
|
|
|
static sprite_t * sprites[20];
|
|
|
|
|
2018-09-12 07:22:34 +03:00
|
|
|
#define TEXT_OFFSET ((window->decorator_flags & DECOR_FLAG_TILED) ? 5 : 10)
|
|
|
|
#define BUTTON_OFFSET ((window->decorator_flags & DECOR_FLAG_TILED) ? 5 : 0)
|
2018-02-25 15:54:39 +03:00
|
|
|
|
|
|
|
static void init_sprite(int id, char * path) {
|
|
|
|
sprites[id] = malloc(sizeof(sprite_t));
|
|
|
|
load_sprite(sprites[id], path);
|
|
|
|
}
|
|
|
|
|
2018-09-12 06:53:08 +03:00
|
|
|
static int get_bounds_fancy(yutani_window_t * window, struct decor_bounds * bounds) {
|
2018-09-12 07:22:34 +03:00
|
|
|
if (window == NULL || !(window->decorator_flags & DECOR_FLAG_TILED)) {
|
2018-09-12 06:53:08 +03:00
|
|
|
bounds->top_height = 33;
|
|
|
|
bounds->bottom_height = 6;
|
|
|
|
bounds->left_width = 6;
|
|
|
|
bounds->right_width = 6;
|
|
|
|
} else {
|
2018-10-11 03:53:55 +03:00
|
|
|
/* Any "exposed" edge gets an extra pixel. */
|
|
|
|
bounds->top_height = 27 + !(window->decorator_flags & DECOR_FLAG_TILE_UP);
|
|
|
|
bounds->bottom_height = !(window->decorator_flags & DECOR_FLAG_TILE_DOWN);
|
|
|
|
bounds->left_width = !(window->decorator_flags & DECOR_FLAG_TILE_LEFT);
|
|
|
|
bounds->right_width = !(window->decorator_flags & DECOR_FLAG_TILE_RIGHT);
|
2018-09-12 06:53:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bounds->width = bounds->left_width + bounds->right_width;
|
|
|
|
bounds->height = bounds->top_height + bounds->bottom_height;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-25 15:54:39 +03:00
|
|
|
static void render_decorations_fancy(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
|
|
|
|
int width = window->width;
|
|
|
|
int height = window->height;
|
|
|
|
|
2018-09-12 06:53:08 +03:00
|
|
|
struct decor_bounds bounds;
|
|
|
|
get_bounds_fancy(window, &bounds);
|
|
|
|
|
|
|
|
for (int j = 0; j < (int)bounds.top_height; ++j) {
|
2018-02-25 15:54:39 +03:00
|
|
|
for (int i = 0; i < width; ++i) {
|
|
|
|
GFX(ctx,i,j) = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-10 09:11:24 +03:00
|
|
|
if (decors_active == DECOR_INACTIVE) decors_active = INACTIVE;
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2018-10-10 09:11:24 +03:00
|
|
|
if ((window->decorator_flags & DECOR_FLAG_TILED)) {
|
2018-02-25 15:54:39 +03:00
|
|
|
for (int i = 0; i < width; ++i) {
|
2018-10-11 03:53:55 +03:00
|
|
|
draw_sprite(ctx, sprites[decors_active + 1], i, -6 + !(window->decorator_flags & DECOR_FLAG_TILE_UP));
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
2018-10-11 03:53:55 +03:00
|
|
|
|
|
|
|
uint32_t clear_color = rgb(62,62,62);
|
|
|
|
if (!(window->decorator_flags & DECOR_FLAG_TILE_DOWN)) {
|
|
|
|
/* Draw bottom line */
|
|
|
|
for (int i = 0; i < (int)window->width; ++i) {
|
|
|
|
GFX(ctx,i,window->height-1) = clear_color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(window->decorator_flags & DECOR_FLAG_TILE_LEFT)) {
|
|
|
|
/* Draw left line */
|
|
|
|
for (int i = 0; i < (int)window->height; ++i) {
|
|
|
|
GFX(ctx,0,i) = clear_color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(window->decorator_flags & DECOR_FLAG_TILE_RIGHT)) {
|
|
|
|
/* Draw right line */
|
|
|
|
for (int i = 0; i < (int)window->height; ++i) {
|
|
|
|
GFX(ctx,window->width-1,i) = clear_color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-10 09:11:24 +03:00
|
|
|
} else {
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2018-10-11 03:53:55 +03:00
|
|
|
uint32_t clear_color = 0x000000;
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2018-10-10 09:11:24 +03:00
|
|
|
for (int j = (int)bounds.top_height; j < height - (int)bounds.bottom_height; ++j) {
|
|
|
|
for (int i = 0; i < (int)bounds.left_width; ++i) {
|
|
|
|
GFX(ctx,i,j) = clear_color;
|
|
|
|
}
|
|
|
|
for (int i = width - (int)bounds.right_width; i < width; ++i) {
|
|
|
|
GFX(ctx,i,j) = clear_color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int j = height - (int)bounds.bottom_height; j < height; ++j) {
|
|
|
|
for (int i = 0; i < width; ++i) {
|
|
|
|
GFX(ctx,i,j) = clear_color;
|
|
|
|
}
|
2018-09-12 07:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 0], 0, 0);
|
|
|
|
for (int i = 0; i < width - (ul_width + ur_width); ++i) {
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 1], i + ul_width, 0);
|
|
|
|
}
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 2], width - ur_width, 0);
|
|
|
|
for (int i = 0; i < height - (u_height + l_height); ++i) {
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 3], 0, i + u_height);
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 4], width - mr_width, i + u_height);
|
|
|
|
}
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 5], 0, height - l_height);
|
|
|
|
for (int i = 0; i < width - (ll_width + lr_width); ++i) {
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 6], i + ll_width, height - l_height);
|
|
|
|
}
|
|
|
|
draw_sprite(ctx, sprites[decors_active + 7], width - lr_width, height - l_height);
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
char * tmp_title = strdup(title);
|
|
|
|
int t_l = strlen(tmp_title);
|
|
|
|
|
2018-09-24 09:06:42 +03:00
|
|
|
#define EXTRA_SPACE 120
|
|
|
|
|
|
|
|
uint32_t title_color = (decors_active == 0) ? rgb(226,226,226) : rgb(147,147,147);
|
2021-07-06 03:39:52 +03:00
|
|
|
tt_set_size(_tt_font, 12);
|
|
|
|
if (tt_string_width(_tt_font, tmp_title) + EXTRA_SPACE > width) {
|
|
|
|
while (t_l >= 0 && (tt_string_width(_tt_font, tmp_title) + EXTRA_SPACE > width)) {
|
|
|
|
tmp_title[t_l] = '\0';
|
|
|
|
t_l--;
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
2021-07-06 03:39:52 +03:00
|
|
|
}
|
2018-02-25 15:54:39 +03:00
|
|
|
|
2021-07-06 03:39:52 +03:00
|
|
|
if (*tmp_title) {
|
|
|
|
int title_offset = (width / 2) - (tt_string_width(_tt_font, tmp_title) / 2);
|
|
|
|
tt_draw_string(ctx, _tt_font, title_offset, TEXT_OFFSET + 14, tmp_title, title_color);
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
free(tmp_title);
|
|
|
|
|
|
|
|
/* Buttons */
|
2018-09-12 07:22:34 +03:00
|
|
|
draw_sprite(ctx, sprites[decors_active + 8], width - 28 + BUTTON_OFFSET, 16 - BUTTON_OFFSET);
|
2018-05-19 10:05:17 +03:00
|
|
|
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
|
2018-09-12 07:22:34 +03:00
|
|
|
draw_sprite(ctx, sprites[decors_active + 9], width - 50 + BUTTON_OFFSET, 16 - BUTTON_OFFSET);
|
2018-05-19 10:05:17 +03:00
|
|
|
}
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int check_button_press_fancy(yutani_window_t * window, int x, int y) {
|
2018-09-12 07:22:34 +03:00
|
|
|
if (x >= (int)window->width - 28 + BUTTON_OFFSET && x <= (int)window->width - 18 + BUTTON_OFFSET &&
|
2018-02-25 15:54:39 +03:00
|
|
|
y >= 16 && y <= 26) {
|
|
|
|
return DECOR_CLOSE;
|
|
|
|
}
|
|
|
|
|
2018-05-19 10:05:17 +03:00
|
|
|
if (!(window->decorator_flags & DECOR_FLAG_NO_MAXIMIZE)) {
|
2018-09-12 07:22:34 +03:00
|
|
|
if (x >= (int)window->width - 50 + BUTTON_OFFSET && x <= (int)window->width - 40 + BUTTON_OFFSET &&
|
2018-05-19 10:05:17 +03:00
|
|
|
y >= 16 && y <= 26) {
|
|
|
|
return DECOR_MAXIMIZE;
|
|
|
|
}
|
2018-04-21 12:57:42 +03:00
|
|
|
}
|
|
|
|
|
2018-02-25 15:54:39 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void decor_init() {
|
2020-04-24 08:30:12 +03:00
|
|
|
init_sprite(0, TTK_FANCY_PATH "active/ul.png");
|
|
|
|
init_sprite(1, TTK_FANCY_PATH "active/um.png");
|
|
|
|
init_sprite(2, TTK_FANCY_PATH "active/ur.png");
|
|
|
|
init_sprite(3, TTK_FANCY_PATH "active/ml.png");
|
|
|
|
init_sprite(4, TTK_FANCY_PATH "active/mr.png");
|
|
|
|
init_sprite(5, TTK_FANCY_PATH "active/ll.png");
|
|
|
|
init_sprite(6, TTK_FANCY_PATH "active/lm.png");
|
|
|
|
init_sprite(7, TTK_FANCY_PATH "active/lr.png");
|
|
|
|
init_sprite(8, TTK_FANCY_PATH "active/button-close.png");
|
|
|
|
init_sprite(9, TTK_FANCY_PATH "active/button-maximize.png");
|
|
|
|
|
|
|
|
init_sprite(INACTIVE + 0, TTK_FANCY_PATH "inactive/ul.png");
|
|
|
|
init_sprite(INACTIVE + 1, TTK_FANCY_PATH "inactive/um.png");
|
|
|
|
init_sprite(INACTIVE + 2, TTK_FANCY_PATH "inactive/ur.png");
|
|
|
|
init_sprite(INACTIVE + 3, TTK_FANCY_PATH "inactive/ml.png");
|
|
|
|
init_sprite(INACTIVE + 4, TTK_FANCY_PATH "inactive/mr.png");
|
|
|
|
init_sprite(INACTIVE + 5, TTK_FANCY_PATH "inactive/ll.png");
|
|
|
|
init_sprite(INACTIVE + 6, TTK_FANCY_PATH "inactive/lm.png");
|
|
|
|
init_sprite(INACTIVE + 7, TTK_FANCY_PATH "inactive/lr.png");
|
|
|
|
init_sprite(INACTIVE + 8, TTK_FANCY_PATH "inactive/button-close.png");
|
|
|
|
init_sprite(INACTIVE + 9, TTK_FANCY_PATH "inactive/button-maximize.png");
|
2018-02-25 15:54:39 +03:00
|
|
|
|
|
|
|
decor_render_decorations = render_decorations_fancy;
|
|
|
|
decor_check_button_press = check_button_press_fancy;
|
2018-09-12 06:53:08 +03:00
|
|
|
decor_get_bounds = get_bounds_fancy;
|
2018-09-24 09:06:42 +03:00
|
|
|
|
2021-08-28 08:50:52 +03:00
|
|
|
_tt_font = tt_font_from_shm("sans-serif.bold");
|
2018-02-25 15:54:39 +03:00
|
|
|
}
|
|
|
|
|