[digesting_libdecor] split state field out of hdr element, delete dead code, eliminate reducible functions

main
Allen Webster 2026-02-28 21:23:41 -08:00
parent 6e0c97bfcd
commit bea30ea7de
2 changed files with 168 additions and 233 deletions

View File

@ -160,18 +160,18 @@ pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
wl_pointer_set_cursor(seat->wl_pointer, seat->serial, seat->cursor_surface, image->hotspot_x, image->hotspot_y); wl_pointer_set_cursor(seat->wl_pointer, seat->serial, seat->cursor_surface, image->hotspot_x, image->hotspot_y);
} }
/* avoid warnings after decoration has been turned off */
if (!GTK_IS_WIDGET(ctx.header) || ctx.active != COMPONENT_SLOT_HEADER){ if (!GTK_IS_WIDGET(ctx.header) || ctx.active != COMPONENT_SLOT_HEADER){
ctx.hdr_focus.type = HEADER_NONE; ctx.hdr_focus.type = HEADER_NONE;
} }
new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header), seat->pointer_x, seat->pointer_y); new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header), seat->pointer_x, seat->pointer_y);
/* only update if widget change so that we keep the state */ /* only update if widget change so that we keep the state */
if (ctx.hdr_focus.widget != new_focus.widget){ if (ctx.hdr_focus.widget != new_focus.widget){
ctx.hdr_focus = new_focus; ctx.hdr_focus = new_focus;
ctx.hdr_state = 0;
} }
ctx.hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT; ctx.hdr_state |= GTK_STATE_FLAG_PRELIGHT;
/* redraw with updated button visuals */ /* redraw with updated button visuals */
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
@ -236,7 +236,7 @@ pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
case HEADER_MIN: case HEADER_MIN:
case HEADER_MAX: case HEADER_MAX:
case HEADER_CLOSE: { case HEADER_CLOSE: {
ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; ctx.hdr_state |= GTK_STATE_FLAG_ACTIVE;
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
}break; }break;
@ -281,7 +281,7 @@ pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
default: break; default: break;
} }
ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; ctx.hdr_state &= ~GTK_STATE_FLAG_ACTIVE;
if (GTK_IS_WIDGET(ctx.header)){ if (GTK_IS_WIDGET(ctx.header)){
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
@ -289,7 +289,7 @@ pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
} }
} }
else{ else{
ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; ctx.hdr_state &= ~GTK_STATE_FLAG_ACTIVE;
if (GTK_IS_WIDGET(ctx.header)) { if (GTK_IS_WIDGET(ctx.header)) {
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
@ -364,7 +364,7 @@ touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial,
case HEADER_MIN: case HEADER_MIN:
case HEADER_MAX: case HEADER_MAX:
case HEADER_CLOSE: { case HEADER_CLOSE: {
ctx.hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; ctx.hdr_state |= GTK_STATE_FLAG_ACTIVE;
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
}break; }break;
@ -398,7 +398,7 @@ touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
if (seat->touch_focus && own_proxy(seat->touch_focus)){ if (seat->touch_focus && own_proxy(seat->touch_focus)){
if (ctx.touch_active != 0){ if (ctx.touch_active != 0){
if (ctx.touch_active == COMPONENT_SLOT_HEADER){ if (ctx.touch_active == COMPONENT_SLOT_HEADER){
switch (ctx.hdr_focus.type) { switch (ctx.hdr_focus.type){
case HEADER_MIN: { case HEADER_MIN: {
if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){
xdg_toplevel_set_minimized(ctx.xdg_toplevel); xdg_toplevel_set_minimized(ctx.xdg_toplevel);
@ -422,13 +422,13 @@ touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
} }
/* unset active/clicked state once released */ /* unset active/clicked state once released */
ctx.hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; ctx.hdr_state &= ~GTK_STATE_FLAG_ACTIVE;
if (GTK_IS_WIDGET(ctx.header)) { if (GTK_IS_WIDGET(ctx.header)) {
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
} }
} }
else{
seat->touch_focus = 0; seat->touch_focus = 0;
ctx.touch_active = 0; ctx.touch_active = 0;
ctx.hdr_focus.widget = 0; ctx.hdr_focus.widget = 0;
@ -437,6 +437,7 @@ touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
} }
} }
}
} }
static void static void
@ -716,7 +717,8 @@ const struct xdg_toplevel_listener xdg_toplevel_listener = {
}; };
static void static void
xdg_toplevel_decoration_configure(void *data, struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode){ xdg_toplevel_decoration_configure(void *data, struct zxdg_toplevel_decoration_v1 *toplevel,
uint32_t mode){
if (!ctx.has_decoration_mode){ if (!ctx.has_decoration_mode){
ctx.has_decoration_mode = true; ctx.has_decoration_mode = true;
ctx.decoration_mode = mode; ctx.decoration_mode = mode;
@ -954,7 +956,6 @@ int main(){
xdg_toplevel_set_title(ctx.xdg_toplevel, "Example Window"); xdg_toplevel_set_title(ctx.xdg_toplevel, "Example Window");
ctx.title = strdup("Example Window"); ctx.title = strdup("Example Window");
draw_decoration();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
/* (nodocs-wl_egl) */ /* (nodocs-wl_egl) */
@ -1011,16 +1012,11 @@ int main(){
} }
} }
/* (egl) eglMakeCurrent */
EGLBoolean make_current_success2 = 0; EGLBoolean make_current_success2 = 0;
if (ctx.egl_surface != EGL_NO_SURFACE){ if (ctx.egl_surface != EGL_NO_SURFACE){
make_current_success2 = eglMakeCurrent(ctx.egl_display, ctx.egl_surface, ctx.egl_surface, ctx.egl_context); make_current_success2 = eglMakeCurrent(ctx.egl_display, ctx.egl_surface, ctx.egl_surface, ctx.egl_context);
} }
/* (egl) eglSwapInterval
** " specifies the minimum number of video frame periods per buffer swap
** for the window associated with the current context "
*/
EGLBoolean swap_interval_success = 0; EGLBoolean swap_interval_success = 0;
if (make_current_success2){ if (make_current_success2){
swap_interval_success = eglSwapInterval(ctx.egl_display, 1); swap_interval_success = eglSwapInterval(ctx.egl_display, 1);
@ -1073,10 +1069,7 @@ int main(){
} }
} }
if (ctx.close_signal){ /* apply new surface config */
exit_loop = 1;
}
if (ctx.has_cached_config){ if (ctx.has_cached_config){
ctx.has_cached_config = 0; ctx.has_cached_config = 0;
if (ctx.cached_config.initialized){ if (ctx.cached_config.initialized){
@ -1099,6 +1092,10 @@ int main(){
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
} }
if (ctx.close_signal){
exit_loop = 1;
}
/* (egl) eglSwapBuffers /* (egl) eglSwapBuffers
** " back-buffered window surface, then the color buffer is copied ** " back-buffered window surface, then the color buffer is copied
** (posted) to the native window associated with that surface " ** (posted) to the native window associated with that surface "
@ -1169,28 +1166,6 @@ decoration_type_from_window_state(enum libdecor_window_state window_state){
return(result); return(result);
} }
static void
free_border_component(struct border_component *border_component){
if (border_component->wl_surface) {
wl_subsurface_destroy(border_component->wl_subsurface);
border_component->wl_subsurface = NULL;
wl_surface_destroy(border_component->wl_surface);
border_component->wl_surface = NULL;
}
if (border_component->wl_buffer != 0){
wl_buffer_destroy(border_component->wl_buffer);
}
if (border_component->data != 0){
munmap(border_component->data, border_component->data_size);
}
border_component->wl_buffer = 0;
border_component->data = 0;
border_component->data_size = 0;
border_component->width = 0;
border_component->height = 0;
}
static enum xdg_toplevel_resize_edge static enum xdg_toplevel_resize_edge
xdg_edge_from_edge(enum libdecor_resize_edge edge){ xdg_edge_from_edge(enum libdecor_resize_edge edge){
enum xdg_toplevel_resize_edge result = XDG_TOPLEVEL_RESIZE_EDGE_NONE; enum xdg_toplevel_resize_edge result = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
@ -1208,26 +1183,19 @@ xdg_edge_from_edge(enum libdecor_resize_edge edge){
return(result); return(result);
} }
void
libdecor_frame_set_fullscreen(struct wl_output *output){
xdg_toplevel_set_fullscreen(ctx.xdg_toplevel, output);
}
void
libdecor_frame_unset_fullscreen(void){
xdg_toplevel_unset_fullscreen(ctx.xdg_toplevel);
}
void void
libdecor_frame_commit(void){ libdecor_frame_commit(void){
Sides2D border_size = border_size_from_window_state(ctx.frame_window_state);
bool csd = false; bool csd = false;
if (ctx.visible && if (ctx.visible &&
ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){
csd = true; csd = true;
} }
Sides2D border_size = {0};
if (csd){
border_size = border_size_from_window_state(ctx.frame_window_state);
}
if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){
int mw = ctx.frame_content_width; int mw = ctx.frame_content_width;
int mh = ctx.frame_content_height; int mh = ctx.frame_content_height;
@ -1270,8 +1238,28 @@ libdecor_frame_commit(void){
g_clear_pointer(&ctx.header, gtk_widget_destroy); g_clear_pointer(&ctx.header, gtk_widget_destroy);
g_clear_pointer(&ctx.window, gtk_widget_destroy); g_clear_pointer(&ctx.window, gtk_widget_destroy);
free_border_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); for (int i = 1; i < COMPONENT_SLOT_COUNT; i += 1){
free_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); struct border_component * border_component = &ctx.component_slot[i];
if (border_component->wl_subsurface != 0){
wl_subsurface_destroy(border_component->wl_subsurface);
border_component->wl_subsurface = 0;
}
if (border_component->wl_surface != 0){
wl_surface_destroy(border_component->wl_surface);
border_component->wl_surface = 0;
}
if (border_component->wl_buffer != 0){
wl_buffer_destroy(border_component->wl_buffer);
border_component->wl_buffer = 0;
}
if (border_component->data != 0){
munmap(border_component->data, border_component->data_size);
border_component->data = 0;
}
border_component->data_size = 0;
border_component->width = 0;
border_component->height = 0;
}
ctx.shadow_showing = false; ctx.shadow_showing = false;
g_clear_pointer(&ctx.title, free); g_clear_pointer(&ctx.title, free);
@ -1283,7 +1271,6 @@ libdecor_frame_commit(void){
Extent2D extent = {0}; Extent2D extent = {0};
extent.w = ctx.frame_content_width; extent.w = ctx.frame_content_width;
extent.h = ctx.frame_content_height; extent.h = ctx.frame_content_height;
if (csd){ if (csd){
extent.x = -border_size.x[0]; extent.x = -border_size.x[0];
extent.y = -border_size.y[0]; extent.y = -border_size.y[0];
@ -1546,200 +1533,161 @@ render_shadow(cairo_t *cr, cairo_surface_t *surface,
//#include "os-compatibility.c" //#include "os-compatibility.c"
#ifndef HAVE_MKOSTEMP #ifndef HAVE_MKOSTEMP
static int static int
set_cloexec_or_close(int fd) set_cloexec_or_close(int fd){
{ bool error = 0;
long flags; long flags;
if (fd == -1) if (fd >= 0){
return -1; if (fcntl(fd, F_GETFD) == -1){
error = 1;
}
else if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1){
error = 1;
}
flags = fcntl(fd, F_GETFD); if (error){
if (flags == -1) close(fd);
goto err; fd = -1;
}
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) }
goto err;
return fd; return fd;
err:
close(fd);
return -1;
} }
#endif #endif
static int static int
create_tmpfile_cloexec(char *tmpname) create_tmpfile_cloexec(char *tmpname){
{
int fd; int fd;
#ifdef HAVE_MKOSTEMP #ifdef HAVE_MKOSTEMP
fd = mkostemp(tmpname, O_CLOEXEC); fd = mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) if (fd >= 0){
unlink(tmpname); unlink(tmpname);
}
#else #else
fd = mkstemp(tmpname); fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd); fd = set_cloexec_or_close(fd);
if (fd >= 0) {
unlink(tmpname); unlink(tmpname);
} }
#endif #endif
return fd; return(fd);
} }
static int static int
os_resize_anonymous_file(int fd, off_t size) os_resize_anonymous_file(int fd, off_t size){
{
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
sigset_t mask; sigset_t mask;
sigset_t old_mask; sigset_t old_mask;
/* posix_fallocate() might be interrupted, so we need to check
* for EINTR and retry in that case.
* However, in the presence of an alarm, the interrupt may trigger
* repeatedly and prevent a large posix_fallocate() to ever complete
* successfully, so we need to first block SIGALRM to prevent
* this.
*/
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, &old_mask); sigprocmask(SIG_BLOCK, &mask, &old_mask);
/*
* Filesystems that do not support fallocate will return EINVAL or
* EOPNOTSUPP. In this case we need to fall back to ftruncate
*/
do { do {
errno = posix_fallocate(fd, 0, size); errno = posix_fallocate(fd, 0, size);
} while (errno == EINTR); } while (errno == EINTR);
sigprocmask(SIG_SETMASK, &old_mask, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL);
if (errno == 0)
return 0; int result = 0;
else if (errno != EINVAL && errno != EOPNOTSUPP) if (errno != 0){
return -1; result = -1;
if (errno == EINVAL || errno == EOPNOTSUPP){
if (ftruncate(fd, size) >= 0){
result = 0;
}
}
}
return(result);
#else
int result = -1;
if (ftruncate(fd, size) >= 0){
result = 0;
}
return(result);
#endif #endif
if (ftruncate(fd, size) < 0)
return -1;
return 0;
} }
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
* CLOEXEC. The file is immediately suitable for mmap()'ing
* the given size at offset zero.
*
* The file should not have a permanent backing store like a disk,
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
*
* The file name is deleted from the file system.
*
* The file is suitable for buffer sharing between processes by
* transmitting the file descriptor over Unix sockets using the
* SCM_RIGHTS methods.
*
* If the C library implements posix_fallocate(), it is used to
* guarantee that disk space is available for the file at the
* given size. If disk space is insufficient, errno is set to ENOSPC.
* If posix_fallocate() is not supported, program may receive
* SIGBUS on accessing mmap()'ed file contents instead.
*
* If the C library implements memfd_create(), it is used to create the
* file purely in memory, without any backing file name on the file
* system, and then sealing off the possibility of shrinking it. This
* can then be checked before accessing mmap()'ed file contents, to
* make sure SIGBUS can't happen. It also avoids requiring
* XDG_RUNTIME_DIR.
*/
int int
libdecor_os_create_anonymous_file(off_t size){ libdecor_os_create_anonymous_file(off_t size){
static const char template[] = "/libdecor-shared-XXXXXX"; static const char key[] = "/libdecor-shared-XXXXXX";
const char *path; int fd = -1;
char *name;
int fd;
#ifdef HAVE_MEMFD_CREATE #ifdef HAVE_MEMFD_CREATE
fd = memfd_create("libdecor", MFD_CLOEXEC | MFD_ALLOW_SEALING); fd = memfd_create("libdecor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd >= 0) { if (fd >= 0){
/* We can add this seal before calling posix_fallocate(), as
* the file is currently zero-sized anyway.
*
* There is also no need to check for the return value, we
* couldn't do anything with it anyway.
*/
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
} else }
#endif #endif
{
path = getenv("XDG_RUNTIME_DIR"); if (fd < 0){
if (!path) { const char *path = getenv("XDG_RUNTIME_DIR");
if (path == 0){
errno = ENOENT; errno = ENOENT;
return -1;
} }
else{
name = malloc(strlen(path) + sizeof(template)); char *name = malloc(strlen(path) + sizeof(key));
if (!name) if (name != 0){
return -1;
strcpy(name, path); strcpy(name, path);
strcat(name, template); strcat(name, key);
fd = create_tmpfile_cloexec(name); fd = create_tmpfile_cloexec(name);
free(name); free(name);
}
if (fd < 0) }
return -1;
} }
if (os_resize_anonymous_file(fd, size) < 0) { if (fd >= 0 && os_resize_anonymous_file(fd, size) < 0){
close(fd); close(fd);
return -1; fd = -1;
} }
return fd; return(fd);
} }
//#include "plugins/gtk/libdecor-gtk.c" //#include "plugins/gtk/libdecor-gtk.c"
struct find_widget_variables{
char *name;
GtkWidget *widget;
} find_widget_variables;
static void static void
gtk_fill_widget_from_name(GtkWidget *widget, void *data){ fill_widget_from_name(GtkWidget *widget, void *data){
struct find_widget_variables *vars = data;
if (vars->widget == 0){
bool match = false; bool match = false;
if (GTK_IS_WIDGET(widget)){ if (GTK_IS_WIDGET(widget)){
struct header_element_data *elem = data;
GtkStyleContext *style_context = gtk_widget_get_style_context(widget); GtkStyleContext *style_context = gtk_widget_get_style_context(widget);
char *style_ctx = gtk_style_context_to_string(style_context, GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE); char *style_str = gtk_style_context_to_string(style_context, GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE);
if (strstr(style_ctx, elem->name) != 0){ if (strstr(style_str, vars->name) != 0){
elem->widget = widget; vars->widget = widget;
match = true; match = true;
} }
free(style_ctx); free(style_str);
} }
/* recursively traverse container */
if (!match && GTK_IS_CONTAINER(widget)){ if (!match && GTK_IS_CONTAINER(widget)){
gtk_container_forall(GTK_CONTAINER(widget), &gtk_fill_widget_from_name, data); gtk_container_forall(GTK_CONTAINER(widget), &fill_widget_from_name, data);
}
} }
} }
static struct header_element_data static GtkWidget*
find_widget_by_type(GtkWidget *widget, enum header_element type){ find_widget_by_type(GtkWidget *root, enum header_element type){
char* name = 0; struct find_widget_variables vars = {0};
switch (type){ switch (type){
case HEADER_FULL: name = "headerbar.titlebar:"; break; case HEADER_FULL: vars.name = "headerbar.titlebar:"; break;
case HEADER_TITLE: name = "label.title:"; break; case HEADER_TITLE: vars.name = "label.title:"; break;
case HEADER_MIN: name = ".minimize"; break; case HEADER_MIN: vars.name = ".minimize"; break;
case HEADER_MAX: name = ".maximize"; break; case HEADER_MAX: vars.name = ".maximize"; break;
case HEADER_CLOSE: name = ".close"; break; case HEADER_CLOSE: vars.name = ".close"; break;
default:break; default:break;
} }
fill_widget_from_name(root, &vars);
struct header_element_data data = {0}; return(vars.widget);
data.name = name;
data.type = type;
gtk_fill_widget_from_name(widget, &data);
return(data);
} }
static struct header_element_data static struct header_element_data
@ -1748,13 +1696,14 @@ get_header_focus(const GtkHeaderBar *header_bar, int x, int y){
struct header_element_data result = {0}; struct header_element_data result = {0};
for (size_t i = 0; i < ARRAY_LENGTH(elems); i += 1){ for (size_t i = 0; i < ARRAY_LENGTH(elems); i += 1){
struct header_element_data elem = find_widget_by_type(GTK_WIDGET(header_bar), elems[i]); GtkWidget *widget = find_widget_by_type(GTK_WIDGET(header_bar), elems[i]);
if (elem.widget){ if (widget != 0){
GtkAllocation allocation; GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(elem.widget), &allocation); gtk_widget_get_allocation(GTK_WIDGET(widget), &allocation);
if (allocation.x <= x && x < allocation.x + allocation.width && if (allocation.x <= x && x < allocation.x + allocation.width &&
allocation.y <= y && y < allocation.y + allocation.height){ allocation.y <= y && y < allocation.y + allocation.height){
result = elem; result.type = elems[i];
result.widget = widget;
break; break;
} }
} }
@ -1897,10 +1846,7 @@ array_append(enum header_element **array, size_t *n, enum header_element item){
static void static void
draw_header_button(cairo_t *cr, cairo_surface_t *surface, draw_header_button(cairo_t *cr, cairo_surface_t *surface,
enum header_element button_type){ enum header_element button_type){
struct header_element_data elem;
GtkWidget *button; GtkWidget *button;
GtkStyleContext* button_style;
GtkStateFlags style_state;
GtkAllocation allocation; GtkAllocation allocation;
@ -1922,19 +1868,18 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface,
GtkBorder border; GtkBorder border;
GtkBorder padding; GtkBorder padding;
elem = find_widget_by_type(ctx.header, button_type); button = find_widget_by_type(ctx.header, button_type);
button = elem.widget;
if (button){ if (button){
button_style = gtk_widget_get_style_context(button); GtkStyleContext *button_style = gtk_widget_get_style_context(button);
style_state = elem.state; GtkStateFlags style_state = 0;
/* change style based on window state and focus */ /* change style based on window state and focus */
if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_ACTIVE)) { if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_ACTIVE)){
style_state |= GTK_STATE_FLAG_BACKDROP; style_state |= GTK_STATE_FLAG_BACKDROP;
} }
if (ctx.hdr_focus.widget == button) { if (ctx.hdr_focus.widget == button){
style_state |= GTK_STATE_FLAG_PRELIGHT; style_state |= GTK_STATE_FLAG_PRELIGHT;
if (ctx.hdr_focus.state & GTK_STATE_FLAG_ACTIVE) { if (ctx.hdr_state & GTK_STATE_FLAG_ACTIVE){
style_state |= GTK_STATE_FLAG_ACTIVE; style_state |= GTK_STATE_FLAG_ACTIVE;
} }
} }
@ -2037,7 +1982,7 @@ static void
draw_border_component(enum component_slot slot){ draw_border_component(enum component_slot slot){
if (slot < COMPONENT_SLOT_COUNT && if (slot < COMPONENT_SLOT_COUNT &&
ctx.component_slot[slot].wl_surface != 0){ ctx.component_slot[slot].wl_surface != 0){
Extent2D extent = extent2d_from_component_slot(slot); struct border_component *component = &ctx.component_slot[slot];
if (slot == COMPONENT_SLOT_SHADOW && ctx.shadow_showing){ if (slot == COMPONENT_SLOT_SHADOW && ctx.shadow_showing){
struct wl_region *input_region; struct wl_region *input_region;
@ -2045,26 +1990,25 @@ draw_border_component(enum component_slot slot){
input_region = wl_compositor_create_region(ctx.wl_compositor); input_region = wl_compositor_create_region(ctx.wl_compositor);
wl_region_add(input_region, 0, 0, extent.w, extent.h); wl_region_add(input_region, 0, 0, extent.w, extent.h);
wl_region_subtract(input_region, -extent.x, -extent.y, ctx.frame_content_width, ctx.frame_content_height); wl_region_subtract(input_region, -extent.x, -extent.y, ctx.frame_content_width, ctx.frame_content_height);
wl_surface_set_input_region(ctx.component_slot[slot].wl_surface, input_region); wl_surface_set_input_region(component->wl_surface, input_region);
wl_region_destroy(input_region); wl_region_destroy(input_region);
} }
struct border_component *component = &ctx.component_slot[slot];
{ {
if (component->wl_buffer != 0){ if (component->wl_buffer != 0){
wl_buffer_destroy(component->wl_buffer); wl_buffer_destroy(component->wl_buffer);
component->wl_buffer = 0;
} }
if (component->data != 0){ if (component->data != 0){
munmap(component->data, component->data_size); munmap(component->data, component->data_size);
}
component->wl_buffer = 0;
component->data = 0; component->data = 0;
}
component->data_size = 0; component->data_size = 0;
component->width = 0; component->width = 0;
component->height = 0; component->height = 0;
} }
Extent2D extent = extent2d_from_component_slot(slot);
{ {
int width = extent.w; int width = extent.w;
int height = extent.h; int height = extent.h;
@ -2125,7 +2069,7 @@ draw_border_component(enum component_slot slot){
/* title */ /* title */
{ {
GtkWidget *label = find_widget_by_type(ctx.header, HEADER_TITLE).widget; GtkWidget *label = find_widget_by_type(ctx.header, HEADER_TITLE);
GtkAllocation allocation; GtkAllocation allocation;
gtk_widget_get_allocation(label, &allocation); gtk_widget_get_allocation(label, &allocation);
@ -2182,11 +2126,7 @@ draw_border_component(enum component_slot slot){
static void static void
draw_title_bar(void){ draw_title_bar(void){
enum libdecor_window_state state; enum libdecor_window_state state = ctx.frame_window_state;
GtkStyleContext *style;
state = ctx.frame_window_state;
style = gtk_widget_get_style_context(ctx.window);
if (!(state & LIBDECOR_WINDOW_STATE_ACTIVE)){ if (!(state & LIBDECOR_WINDOW_STATE_ACTIVE)){
gtk_widget_set_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP, true); gtk_widget_set_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP, true);
@ -2194,14 +2134,13 @@ draw_title_bar(void){
else{ else{
gtk_widget_unset_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP); gtk_widget_unset_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP);
} }
GtkStyleContext *style = gtk_widget_get_style_context(ctx.window);
if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){ if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){
gtk_style_context_remove_class(style, "maximized"); gtk_style_context_remove_class(style, "maximized");
} }
else{ else{
gtk_style_context_add_class(style, "maximized"); gtk_style_context_add_class(style, "maximized");
} }
gtk_widget_show_all(ctx.window); gtk_widget_show_all(ctx.window);
int pref_width; int pref_width;
@ -2327,8 +2266,9 @@ update_touch_focus(struct seat *seat, wl_fixed_t x, wl_fixed_t y){
struct header_element_data new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header), wl_fixed_to_int(x), wl_fixed_to_int(y)); struct header_element_data new_focus = get_header_focus(GTK_HEADER_BAR(ctx.header), wl_fixed_to_int(x), wl_fixed_to_int(y));
if (ctx.hdr_focus.widget != new_focus.widget){ if (ctx.hdr_focus.widget != new_focus.widget){
ctx.hdr_focus = new_focus; ctx.hdr_focus = new_focus;
ctx.hdr_state = 0;
} }
ctx.hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT; ctx.hdr_state |= GTK_STATE_FLAG_PRELIGHT;
draw_title_bar(); draw_title_bar();
wl_surface_commit(ctx.wl_surface); wl_surface_commit(ctx.wl_surface);
} }

View File

@ -146,11 +146,9 @@ enum titlebar_gesture_state {
TITLEBAR_GESTURE_STATE_DISCARDED, TITLEBAR_GESTURE_STATE_DISCARDED,
}; };
struct header_element_data { struct header_element_data{
const char *name;
enum header_element type; enum header_element type;
GtkWidget *widget; GtkWidget *widget;
GtkStateFlags state;
}; };
enum decoration_type { enum decoration_type {
@ -253,8 +251,6 @@ enum titlebar_gesture {
void libdecor_frame_show_window_menu(struct wl_seat *wl_seat, uint32_t serial, int x, int y); void libdecor_frame_show_window_menu(struct wl_seat *wl_seat, uint32_t serial, int x, int y);
void libdecor_frame_commit(void); void libdecor_frame_commit(void);
void libdecor_frame_set_fullscreen(struct wl_output *output);
void libdecor_frame_unset_fullscreen(void);
// #include "libdecor-cairo-blur.h" // #include "libdecor-cairo-blur.h"
@ -281,8 +277,6 @@ static void do_map(void);
static const char *libdecor_gtk_proxy_tag = "libdecor-gtk"; static const char *libdecor_gtk_proxy_tag = "libdecor-gtk";
static void libdecor_plugin_gtk_frame_free(void);
static void libdecor_plugin_gtk_frame_commit(void);
static Sides2D border_size_from_window_state(enum libdecor_window_state window_state); static Sides2D border_size_from_window_state(enum libdecor_window_state window_state);
static struct wl_cursor* wl_cursor_from_pos(int x, int y); static struct wl_cursor* wl_cursor_from_pos(int x, int y);
@ -386,6 +380,7 @@ typedef struct Ctx{
GtkWidget *window; GtkWidget *window;
GtkWidget *header; GtkWidget *header;
struct header_element_data hdr_focus; struct header_element_data hdr_focus;
GtkStateFlags hdr_state;
cairo_surface_t *shadow_blur; cairo_surface_t *shadow_blur;