If a user has multiple active XKB layouts but only one of them has ASCII keysyms on the base level, then ctrl+<XY> might actually never work, because these keys aren't available in the current layout. This patch tries to find a layout of the user that actually _has_ ascii keysyms on the base level and passes this information along with the normal keysym information. The TSM layer can now use this ascii keysym instead of the normal unicode keysym to handle ctrl+<XY> shortcuts. This is the same way xterm et. al. handle this, so it seems to be a good idea to do this in TSM, too. Reported (and mainly written) by Ran Benita. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
614 lines
16 KiB
C
614 lines
16 KiB
C
/*
|
|
* wlt - Theme Helper
|
|
*
|
|
* Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files
|
|
* (the "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* Wayland Terminal theme/decoration drawing helper
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <linux/input.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wayland-client.h>
|
|
#include "log.h"
|
|
#include "shl_misc.h"
|
|
#include "wlt_main.h"
|
|
#include "wlt_theme.h"
|
|
#include "wlt_toolkit.h"
|
|
|
|
#define LOG_SUBSYSTEM "wlt_theme"
|
|
|
|
enum theme_location {
|
|
LOC_NOWHERE,
|
|
LOC_SOMEWHERE,
|
|
LOC_RESIZE_TOP,
|
|
LOC_RESIZE_BOTTOM,
|
|
LOC_RESIZE_LEFT,
|
|
LOC_RESIZE_RIGHT,
|
|
LOC_RESIZE_TOP_LEFT,
|
|
LOC_RESIZE_TOP_RIGHT,
|
|
LOC_RESIZE_BOTTOM_LEFT,
|
|
LOC_RESIZE_BOTTOM_RIGHT,
|
|
LOC_CONTROL,
|
|
LOC_MINIMIZE,
|
|
LOC_MAXIMIZE,
|
|
LOC_CLOSE,
|
|
};
|
|
|
|
struct wlt_theme {
|
|
struct wlt_window *wnd;
|
|
struct wlt_widget *widget;
|
|
struct wlt_shm_buffer buffer;
|
|
struct wlt_rect alloc;
|
|
unsigned int control_height;
|
|
unsigned int frame_width;
|
|
unsigned int resize_margin;
|
|
unsigned int button_size;
|
|
unsigned int button_padding;
|
|
unsigned int button_margin;
|
|
|
|
unsigned int pointer_x;
|
|
unsigned int pointer_y;
|
|
unsigned int pointer_loc;
|
|
bool pointer_pressed;
|
|
unsigned int pointer_grabbed;
|
|
};
|
|
|
|
static void draw_control(struct wlt_theme *theme)
|
|
{
|
|
uint8_t *dst;
|
|
uint32_t *line, backcol;
|
|
unsigned int i, j;
|
|
unsigned int b1off, b2off, b3off;
|
|
|
|
/* background */
|
|
if (theme->pointer_loc == LOC_NOWHERE)
|
|
backcol = (0x60 << 24) | (0xaa << 16) |
|
|
(0xaa << 8) | 0xaa;
|
|
else
|
|
backcol = (0x20 << 24) | (0xee << 16) |
|
|
(0xee << 8) | 0xee;
|
|
dst = theme->buffer.data;
|
|
for (i = 0; i < theme->control_height; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->buffer.width; ++j) {
|
|
if (i == 0 || i == theme->control_height - 1 ||
|
|
j == 0 || j == theme->buffer.width - 1)
|
|
line[j] = 0xff << 24;
|
|
else
|
|
line[j] = backcol;
|
|
}
|
|
dst += theme->buffer.stride;
|
|
}
|
|
|
|
/* buttons */
|
|
b1off = theme->buffer.width - theme->button_margin - theme->button_size;
|
|
b2off = b1off - theme->button_padding - theme->button_size;
|
|
b3off = b2off - theme->button_padding - theme->button_size;
|
|
dst = theme->buffer.data + theme->buffer.stride * theme->button_margin;
|
|
for (i = 0; i < theme->button_size; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->buffer.width; ++j) {
|
|
if (j >= b1off &&
|
|
j < b1off + theme->button_size) {
|
|
if (i == 0 ||
|
|
i == theme->button_size - 1 ||
|
|
j == b1off ||
|
|
j == b1off + theme->button_size - 1)
|
|
line[j] = 0xff << 24;
|
|
else if (theme->pointer_loc == LOC_CLOSE &&
|
|
theme->pointer_pressed &&
|
|
theme->pointer_grabbed == LOC_CLOSE)
|
|
line[j] = (0xff << 24) | 0x1f1f1f1f;
|
|
else if (theme->pointer_loc == LOC_CLOSE &&
|
|
!theme->pointer_pressed)
|
|
line[j] = 0xffffffff;
|
|
else
|
|
line[j] = (0xff << 24) | 0x33333333;
|
|
} else if (j >= b2off &&
|
|
j < b2off + theme->button_size) {
|
|
if (i == 0 ||
|
|
i == theme->button_size - 1 ||
|
|
j == b2off ||
|
|
j == b2off + theme->button_size - 1)
|
|
line[j] = 0xff << 24;
|
|
else if (theme->pointer_loc == LOC_MAXIMIZE &&
|
|
theme->pointer_pressed &&
|
|
theme->pointer_grabbed == LOC_MAXIMIZE)
|
|
line[j] = (0xff << 24) | 0x1f1f1f1f;
|
|
else if (theme->pointer_loc == LOC_MAXIMIZE &&
|
|
!theme->pointer_pressed)
|
|
line[j] = 0xffffffff;
|
|
else
|
|
line[j] = (0xff << 24) | 0x66666666;
|
|
} else if (j >= b3off &&
|
|
j < b3off + theme->button_size) {
|
|
if (i == 0 ||
|
|
i == theme->button_size - 1 ||
|
|
j == b3off ||
|
|
j == b3off + theme->button_size - 1)
|
|
line[j] = 0xff << 24;
|
|
else if (theme->pointer_loc == LOC_MINIMIZE &&
|
|
theme->pointer_pressed &&
|
|
theme->pointer_grabbed == LOC_MINIMIZE)
|
|
line[j] = (0xff << 24) | 0x1f1f1f1f;
|
|
else if (theme->pointer_loc == LOC_MINIMIZE &&
|
|
!theme->pointer_pressed)
|
|
line[j] = 0xffffffff;
|
|
else
|
|
line[j] = (0xff << 24) | 0xaaaaaaaa;
|
|
}
|
|
}
|
|
dst += theme->buffer.stride;
|
|
}
|
|
}
|
|
|
|
static void draw_frame(struct wlt_theme *theme)
|
|
{
|
|
uint8_t *dst;
|
|
uint32_t *line;
|
|
unsigned int i, j, height;
|
|
|
|
/* top frame */
|
|
dst = theme->buffer.data + theme->buffer.stride *
|
|
theme->control_height;
|
|
for (i = 0; i < theme->frame_width; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->buffer.width; ++j)
|
|
line[j] = 0xa0 << 24;
|
|
dst += theme->buffer.stride;
|
|
}
|
|
|
|
/* bottom frame */
|
|
dst = theme->buffer.data + theme->buffer.stride *
|
|
(theme->buffer.height - theme->frame_width);
|
|
for (i = 0; i < theme->frame_width; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->buffer.width; ++j)
|
|
line[j] = 0xa0 << 24;
|
|
dst += theme->buffer.stride;
|
|
}
|
|
|
|
/* left frame */
|
|
dst = theme->buffer.data + theme->buffer.stride *
|
|
(theme->control_height + theme->frame_width);
|
|
height = theme->buffer.height - theme->control_height -
|
|
theme->frame_width * 2;
|
|
for (i = 0; i < height; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->frame_width; ++j)
|
|
line[j] = 0xa0 << 24;
|
|
dst += theme->buffer.stride;
|
|
}
|
|
|
|
/* right frame */
|
|
dst = theme->buffer.data + theme->buffer.stride *
|
|
(theme->control_height + theme->frame_width);
|
|
height = theme->buffer.height - theme->control_height -
|
|
theme->frame_width * 2;
|
|
for (i = 0; i < height; ++i) {
|
|
line = (uint32_t*)dst;
|
|
line += theme->buffer.width - theme->frame_width;
|
|
for (j = 0; j < theme->frame_width; ++j)
|
|
line[j] = 0xa0 << 24;
|
|
dst += theme->buffer.stride;
|
|
}
|
|
}
|
|
|
|
static void widget_draw_fallback(struct wlt_theme *theme)
|
|
{
|
|
uint8_t *dst;
|
|
uint32_t *line;
|
|
unsigned int i, j;
|
|
|
|
dst = theme->buffer.data;
|
|
for (i = 0; i < theme->buffer.height; ++i) {
|
|
line = (uint32_t*)dst;
|
|
for (j = 0; j < theme->buffer.width; ++j) {
|
|
line[j] = 0xff << 24;
|
|
}
|
|
dst += theme->buffer.stride;
|
|
}
|
|
}
|
|
|
|
static void widget_redraw(struct wlt_widget *widget, unsigned int flags,
|
|
void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
unsigned int width, height;
|
|
|
|
if (flags & WLT_WINDOW_FULLSCREEN)
|
|
return;
|
|
|
|
width = theme->buffer.width;
|
|
height = theme->buffer.height;
|
|
if (width < 2 ||
|
|
width < 2 * theme->frame_width ||
|
|
width < 2 * theme->button_margin + 2 * theme->button_padding +
|
|
3 * theme->button_size) {
|
|
widget_draw_fallback(theme);
|
|
} else if (height < theme->control_height + 2 * theme->frame_width) {
|
|
widget_draw_fallback(theme);
|
|
} else {
|
|
draw_frame(theme);
|
|
draw_control(theme);
|
|
}
|
|
}
|
|
|
|
static void widget_prepare_resize(struct wlt_widget *widget,
|
|
unsigned int flags,
|
|
unsigned int width, unsigned int height,
|
|
unsigned int *min_width,
|
|
unsigned int *min_height,
|
|
unsigned int *new_width,
|
|
unsigned int *new_height,
|
|
void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
unsigned int minw, minh;
|
|
|
|
if (flags & WLT_WINDOW_FULLSCREEN)
|
|
return;
|
|
|
|
/* set minimal size */
|
|
minw = 2 * theme->button_margin + 2 * theme->button_padding +
|
|
3 * theme->button_size + *new_width;
|
|
minh = theme->button_size + 2 * theme->button_padding +
|
|
2 * theme->frame_width + *new_height;
|
|
if (*min_width < minw)
|
|
*min_width = minw;
|
|
if (*min_height < minh)
|
|
*min_height = minh;
|
|
|
|
/* set margin size */
|
|
minw = 2 * theme->frame_width;
|
|
minh = theme->control_height + 2 * theme->frame_width;
|
|
|
|
*new_width += minw;
|
|
*new_height += minh;
|
|
}
|
|
|
|
static void widget_resize(struct wlt_widget *widget, unsigned int flags,
|
|
struct wlt_rect *alloc, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
unsigned int nwidth, nheight;
|
|
|
|
wlt_window_get_buffer(theme->wnd, alloc, &theme->buffer);
|
|
memcpy(&theme->alloc, alloc, sizeof(*alloc));
|
|
|
|
if (flags & WLT_WINDOW_FULLSCREEN)
|
|
return;
|
|
|
|
alloc->x = theme->frame_width;
|
|
alloc->y = theme->control_height + theme->frame_width;
|
|
nwidth = alloc->width - 2 * theme->frame_width;
|
|
nheight = alloc->height;
|
|
nheight -= (theme->control_height + 2 * theme->frame_width);
|
|
|
|
if (nwidth > alloc->width || nheight > alloc->height) {
|
|
alloc->width = 0;
|
|
alloc->height = 0;
|
|
} else {
|
|
alloc->width = nwidth;
|
|
alloc->height = nheight;
|
|
}
|
|
}
|
|
|
|
static unsigned int get_pointer_location(struct wlt_theme *theme)
|
|
{
|
|
unsigned int m = theme->resize_margin;
|
|
unsigned int b1off, b2off, b3off;
|
|
|
|
if (theme->pointer_y < m) {
|
|
if (theme->pointer_x < m)
|
|
return LOC_RESIZE_TOP_LEFT;
|
|
else if (theme->pointer_x >= theme->buffer.width - m)
|
|
return LOC_RESIZE_TOP_RIGHT;
|
|
else
|
|
return LOC_RESIZE_TOP;
|
|
}
|
|
|
|
if (theme->pointer_y >= theme->buffer.height - m) {
|
|
if (theme->pointer_x < m)
|
|
return LOC_RESIZE_BOTTOM_LEFT;
|
|
else if (theme->pointer_x >= theme->buffer.width - m)
|
|
return LOC_RESIZE_BOTTOM_RIGHT;
|
|
else
|
|
return LOC_RESIZE_BOTTOM;
|
|
}
|
|
|
|
if (theme->pointer_x < m)
|
|
return LOC_RESIZE_LEFT;
|
|
|
|
if (theme->pointer_x >= theme->buffer.width - m)
|
|
return LOC_RESIZE_RIGHT;
|
|
|
|
if (theme->pointer_y < theme->control_height) {
|
|
b1off = theme->buffer.width - theme->button_margin -
|
|
theme->button_size;
|
|
b2off = b1off - theme->button_padding - theme->button_size;
|
|
b3off = b2off - theme->button_padding - theme->button_size;
|
|
|
|
if (theme->pointer_y >= theme->button_margin &&
|
|
theme->pointer_y < theme->control_height -
|
|
theme->button_margin) {
|
|
if (theme->pointer_x >= b1off &&
|
|
theme->pointer_x < b1off + theme->button_size)
|
|
return LOC_CLOSE;
|
|
if (theme->pointer_x >= b2off &&
|
|
theme->pointer_x < b2off + theme->button_size)
|
|
return LOC_MAXIMIZE;
|
|
if (theme->pointer_x >= b3off &&
|
|
theme->pointer_x < b3off + theme->button_size)
|
|
return LOC_MINIMIZE;
|
|
}
|
|
|
|
return LOC_CONTROL;
|
|
}
|
|
|
|
return LOC_SOMEWHERE;
|
|
}
|
|
|
|
static void set_pointer_location(struct wlt_theme *theme, unsigned int loc)
|
|
{
|
|
if (theme->pointer_loc == loc)
|
|
return;
|
|
|
|
theme->pointer_loc = loc;
|
|
if (loc == LOC_NOWHERE) {
|
|
theme->pointer_x = -1;
|
|
theme->pointer_y = -1;
|
|
}
|
|
|
|
wlt_window_schedule_redraw(theme->wnd);
|
|
}
|
|
|
|
static void widget_pointer_motion(struct wlt_widget *widget,
|
|
unsigned int x, unsigned int y, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
if (!wlt_rect_contains(&theme->alloc, x, y)) {
|
|
set_pointer_location(theme, LOC_NOWHERE);
|
|
return;
|
|
} else {
|
|
theme->pointer_x = x - theme->alloc.x;
|
|
theme->pointer_y = y - theme->alloc.y;
|
|
set_pointer_location(theme, get_pointer_location(theme));
|
|
}
|
|
|
|
switch (theme->pointer_loc) {
|
|
case LOC_RESIZE_LEFT:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_LEFT);
|
|
break;
|
|
case LOC_RESIZE_RIGHT:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_RIGHT);
|
|
break;
|
|
case LOC_RESIZE_TOP:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_BOTTOM);
|
|
break;
|
|
case LOC_RESIZE_TOP_LEFT:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP_LEFT);
|
|
break;
|
|
case LOC_RESIZE_TOP_RIGHT:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP_RIGHT);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM_LEFT:
|
|
wlt_window_set_cursor(theme->wnd,
|
|
WLT_CURSOR_BOTTOM_LEFT);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM_RIGHT:
|
|
wlt_window_set_cursor(theme->wnd,
|
|
WLT_CURSOR_BOTTOM_RIGHT);
|
|
break;
|
|
default:
|
|
wlt_window_set_cursor(theme->wnd, WLT_CURSOR_LEFT_PTR);
|
|
}
|
|
}
|
|
|
|
static void widget_pointer_enter(struct wlt_widget *widget,
|
|
unsigned int x, unsigned int y, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
widget_pointer_motion(widget, x, y, theme);
|
|
}
|
|
|
|
static void widget_pointer_leave(struct wlt_widget *widget, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
if (theme->pointer_pressed) {
|
|
theme->pointer_pressed = false;
|
|
wlt_window_schedule_redraw(theme->wnd);
|
|
}
|
|
|
|
set_pointer_location(theme, LOC_NOWHERE);
|
|
}
|
|
|
|
static void button_action(struct wlt_theme *theme)
|
|
{
|
|
if (theme->pointer_grabbed != theme->pointer_loc)
|
|
return;
|
|
|
|
switch (theme->pointer_loc) {
|
|
case LOC_CLOSE:
|
|
wlt_window_close(theme->wnd);
|
|
break;
|
|
case LOC_MAXIMIZE:
|
|
wlt_window_toggle_maximize(theme->wnd);
|
|
break;
|
|
case LOC_MINIMIZE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void widget_pointer_button(struct wlt_widget *widget,
|
|
uint32_t button, uint32_t state, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
if (button != BTN_LEFT)
|
|
return;
|
|
|
|
if (state != WL_POINTER_BUTTON_STATE_PRESSED) {
|
|
if (theme->pointer_pressed) {
|
|
button_action(theme);
|
|
theme->pointer_pressed = false;
|
|
theme->pointer_grabbed = LOC_NOWHERE;
|
|
wlt_window_schedule_redraw(theme->wnd);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!theme->pointer_pressed) {
|
|
theme->pointer_pressed = true;
|
|
theme->pointer_grabbed = theme->pointer_loc;
|
|
wlt_window_schedule_redraw(theme->wnd);
|
|
}
|
|
|
|
switch (theme->pointer_loc) {
|
|
case LOC_RESIZE_LEFT:
|
|
wlt_window_resize(theme->wnd, WL_SHELL_SURFACE_RESIZE_LEFT);
|
|
break;
|
|
case LOC_RESIZE_RIGHT:
|
|
wlt_window_resize(theme->wnd, WL_SHELL_SURFACE_RESIZE_RIGHT);
|
|
break;
|
|
case LOC_RESIZE_TOP:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_TOP);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_BOTTOM);
|
|
break;
|
|
case LOC_RESIZE_TOP_LEFT:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_TOP_LEFT);
|
|
break;
|
|
case LOC_RESIZE_TOP_RIGHT:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_TOP_RIGHT);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM_LEFT:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT);
|
|
break;
|
|
case LOC_RESIZE_BOTTOM_RIGHT:
|
|
wlt_window_resize(theme->wnd,
|
|
WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT);
|
|
break;
|
|
case LOC_CONTROL:
|
|
wlt_window_move(theme->wnd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static bool widget_key(struct wlt_widget *widget, unsigned int mask,
|
|
uint32_t sym, uint32_t ascii, uint32_t state,
|
|
bool handled, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
if (handled || state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
|
return false;
|
|
|
|
if (SHL_HAS_BITS(mask, wlt_conf.grab_fullscreen->mods) &&
|
|
sym == wlt_conf.grab_fullscreen->keysym) {
|
|
wlt_window_toggle_fullscreen(theme->wnd);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static void widget_destroy(struct wlt_widget *widget, void *data)
|
|
{
|
|
struct wlt_theme *theme = data;
|
|
|
|
log_debug("destroy theme");
|
|
|
|
free(theme);
|
|
}
|
|
|
|
int wlt_theme_new(struct wlt_theme **out, struct wlt_window *wnd)
|
|
{
|
|
struct wlt_theme *theme;
|
|
int ret;
|
|
|
|
if (!out || !wnd)
|
|
return -EINVAL;
|
|
|
|
log_debug("create new theme");
|
|
|
|
theme = malloc(sizeof(*theme));
|
|
if (!theme)
|
|
return -ENOMEM;
|
|
memset(theme, 0, sizeof(*theme));
|
|
theme->wnd = wnd;
|
|
theme->control_height = 25;
|
|
theme->frame_width = 5;
|
|
theme->resize_margin = 5;
|
|
theme->button_size = 15;
|
|
theme->button_padding = 3;
|
|
theme->button_margin = 5;
|
|
theme->pointer_grabbed = LOC_NOWHERE;
|
|
set_pointer_location(theme, LOC_NOWHERE);
|
|
|
|
ret = wlt_window_create_widget(wnd, &theme->widget, theme);
|
|
if (ret) {
|
|
log_error("cannot create widget");
|
|
goto err_free;
|
|
}
|
|
|
|
wlt_widget_set_destroy_cb(theme->widget, widget_destroy);
|
|
wlt_widget_set_redraw_cb(theme->widget, widget_redraw);
|
|
wlt_widget_set_resize_cb(theme->widget, widget_prepare_resize,
|
|
widget_resize);
|
|
wlt_widget_set_pointer_cb(theme->widget, widget_pointer_enter,
|
|
widget_pointer_leave, widget_pointer_motion,
|
|
widget_pointer_button);
|
|
wlt_widget_set_keyboard_cb(theme->widget, widget_key);
|
|
*out = theme;
|
|
return 0;
|
|
|
|
err_free:
|
|
free(theme);
|
|
return ret;
|
|
}
|
|
|
|
void wlt_theme_destroy(struct wlt_theme *theme)
|
|
{
|
|
if (!theme)
|
|
return;
|
|
|
|
wlt_widget_destroy(theme->widget);
|
|
}
|