Compare commits

..

No commits in common. "070ab2f42f0c155e806e0677fe5cdc7eccab626e" and "1acd34888634a9f2a52225d3dfc40a1a26207cab" have entirely different histories.

2 changed files with 341 additions and 307 deletions

View File

@ -67,14 +67,14 @@ GL_FUNCS_XLIST(X)
static Ctx ctx = {0}; static Ctx ctx = {0};
static void static void
shm_format(void *udata, struct wl_shm *wl_shm, CSD_U32 format){} shm_format(void *udata, struct wl_shm *wl_shm, uint32_t format){}
static const struct wl_shm_listener shm_listener = { static const struct wl_shm_listener shm_listener = {
shm_format shm_format
}; };
static void static void
xdg_wm_base_ping(void *udata, struct xdg_wm_base *xdg_wm_base, CSD_U32 serial){ xdg_wm_base_ping(void *udata, struct xdg_wm_base *xdg_wm_base, uint32_t serial){
xdg_wm_base_pong(xdg_wm_base, serial); xdg_wm_base_pong(xdg_wm_base, serial);
} }
@ -83,78 +83,169 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = {
}; };
static void static void
pointer_enter(void *udata, struct wl_pointer *wl_pointer, CSD_U32 serial, pointer_enter(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
struct wl_surface *surface, wl_fixed_t fx, wl_fixed_t fy){ struct wl_surface *surface, wl_fixed_t fx, wl_fixed_t fy){
CSD_Window *window = &ctx.window; CSD_Window *window = &ctx.window;
CSD_GTK_Window *gtk_window = &ctx.gtk_window; CSD_GTK_Window *gtk_window = &ctx.gtk_window;
CSD_S32 surface_off[2] = {0}; int32_t x = wl_fixed_to_int(fx);
int32_t y = wl_fixed_to_int(fy);
if (surface == window->main_wl_surface){ if (surface == window->main_wl_surface){
// surface_off = {0,0} printf("pointer_enter (main) %d,%d\n", x, y);
} }
else if (surface == gtk_window->titlebar.wl_surface){ else if (surface == gtk_window->titlebar.wl_surface){
memcpy(surface_off, gtk_window->titlebar.p, sizeof(surface_off)); x += gtk_window->titlebar.p[0];
y += gtk_window->titlebar.p[1];
printf("pointer_enter (titlebar) %d,%d\n", x, y);
} }
else if (surface == gtk_window->shadow.wl_surface){ else if (surface == gtk_window->shadow.wl_surface){
memcpy(surface_off, gtk_window->shadow.p, sizeof(surface_off)); x += gtk_window->shadow.p[0];
y += gtk_window->shadow.p[1];
printf("pointer_enter (shadow) %d,%d\n", x, y);
} }
else{
CSD_Seat *seat = &ctx.seat; printf("pointer_enter (unidentified) %d,%d\n", x, y);
seat->hover_surface = surface; }
seat->hover_p[0] = surface_off[0] + wl_fixed_to_int(fx); window->serial = serial;
seat->hover_p[1] = surface_off[1] + wl_fixed_to_int(fy); ctx.hover_surface = surface;
seat->serial = serial; ctx.hover_p[0] = x;
ctx.hover_p[1] = y;
#if 0
if (csd_gtk_pointer_enter(gtk_window, serial, surface, fx, fy)){
// handled by gtk
}
else if (surface == ctx.main_wl_surface){
int32_t x = wl_fixed_to_int(fx);
int32_t y = wl_fixed_to_int(fy);
// my event
}
else{
// unknown surface
}
ctx.hover_surface = surface;
#endif
} }
static void static void
pointer_leave(void *udata, struct wl_pointer *wl_pointer, pointer_leave(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
CSD_U32 serial, struct wl_surface *surface){ struct wl_surface *surface){
CSD_Seat *seat = &ctx.seat;
seat->hover_surface = 0;
seat->serial = serial;
}
static void
pointer_motion(void *udata, struct wl_pointer *wl_pointer,
CSD_U32 time, wl_fixed_t fx, wl_fixed_t fy){
CSD_Window *window = &ctx.window; CSD_Window *window = &ctx.window;
CSD_GTK_Window *gtk_window = &ctx.gtk_window; CSD_GTK_Window *gtk_window = &ctx.gtk_window;
CSD_Seat *seat = &ctx.seat; if (surface == window->main_wl_surface){
printf("pointer_leave (main)\n");
CSD_S32 surface_off[2] = {0};
if (seat->hover_surface == window->main_wl_surface){
// surface_off = {0,0}
} }
else if (seat->hover_surface == gtk_window->titlebar.wl_surface){ else if (surface == gtk_window->titlebar.wl_surface){
memcpy(surface_off, gtk_window->titlebar.p, sizeof(surface_off)); printf("pointer_leave (titlebar)\n");
} }
else if (seat->hover_surface == gtk_window->shadow.wl_surface){ else if (surface == gtk_window->shadow.wl_surface){
memcpy(surface_off, gtk_window->shadow.p, sizeof(surface_off)); printf("pointer_leave (shadow)\n");
} }
else{
seat->hover_p[0] = surface_off[0] + wl_fixed_to_int(fx); printf("pointer_leave (unidentified)\n");
seat->hover_p[1] = surface_off[1] + wl_fixed_to_int(fy); }
ctx.hover_surface = 0;
#if 0
if (csd_gtk_pointer_leave(gtk_window, serial, surface)){
// handled by gtk
}
else if (surface == ctx.main_wl_surface){
int32_t x = wl_fixed_to_int(fx);
int32_t y = wl_fixed_to_int(fy);
// my event
}
else{
// unknown
}
#endif
} }
static void static void
pointer_button(void *udata, struct wl_pointer *wl_pointer, pointer_motion(void *udata, struct wl_pointer *wl_pointer, uint32_t time,
CSD_U32 serial, CSD_U32 time, CSD_U32 button, CSD_U32 state){ wl_fixed_t fx, wl_fixed_t fy){
CSD_Seat *seat = &ctx.seat;
CSD_Window *window = &ctx.window; CSD_Window *window = &ctx.window;
CSD_GTK_Window *gtk_window = &ctx.gtk_window; CSD_GTK_Window *gtk_window = &ctx.gtk_window;
{
ctx.has_event = 1; int32_t x = wl_fixed_to_int(fx);
ctx.event_button = button; int32_t y = wl_fixed_to_int(fy);
ctx.event_button_state = state; if (ctx.hover_surface == window->main_wl_surface){
printf("pointer_motion (main) %d,%d\n", x, y);
} }
seat->serial = serial; else if (ctx.hover_surface == gtk_window->titlebar.wl_surface){
x += gtk_window->titlebar.p[0];
y += gtk_window->titlebar.p[1];
printf("pointer_motion (titlebar) %d,%d\n", x, y);
}
else if (ctx.hover_surface == gtk_window->shadow.wl_surface){
x += gtk_window->shadow.p[0];
y += gtk_window->shadow.p[1];
printf("pointer_motion (shadow) %d,%d\n", x, y);
}
else{
printf("pointer_motion (unidentified) %d,%d\n", x, y);
}
ctx.hover_p[0] = x;
ctx.hover_p[1] = y;
#if 0
if (csd_gtk_pointer_motion(&ctx.gtk_window, ctx.hover_surface,
time, fx, fy)){
// handled by gtk
}
else if (surface == ctx.main_wl_surface){
int32_t x = wl_fixed_to_int(fx);
int32_t y = wl_fixed_to_int(fy);
// my event
}
else{
// unknown
}
#endif
}
static void
pointer_button(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state){
CSD_Window *window = &ctx.window;
CSD_GTK_Window *gtk_window = &ctx.gtk_window;
char *state_str = (state == 1?"press":"release");
if (button == BTN_LEFT){
printf("pointer_button (left) %s\n", state_str);
}
else if (button == BTN_RIGHT){
printf("pointer_button (right) %s\n", state_str);
}
else if (button == BTN_MIDDLE){
printf("pointer_button (middle) %s\n", state_str);
}
else{
printf("pointer_button (unidentified) %s\n", state_str);
}
if (state){
gtk_window->button = button;
}
window->serial = serial;
#if 0
if (csd_gtk_pointer_button(&ctx.gtk_window, serial, time, button, state)){
// handled by gtk
}
else if (surface == ctx.main_wl_surface){
int32_t x = wl_fixed_to_int(fx);
int32_t y = wl_fixed_to_int(fy);
// my event
}
else{
// unknown
}
#endif
} }
static void static void
pointer_axis(void *udata, struct wl_pointer *wl_pointer, pointer_axis(void *udata, struct wl_pointer *wl_pointer,
CSD_U32 time, CSD_U32 axis, wl_fixed_t fv){ uint32_t time, uint32_t axis, wl_fixed_t fv){
int v = wl_fixed_to_int(fv); int v = wl_fixed_to_int(fv);
printf("pointer_axis %u,%d\n", axis, v);
} }
static const struct wl_pointer_listener pointer_listener = { static const struct wl_pointer_listener pointer_listener = {
@ -166,15 +257,14 @@ static const struct wl_pointer_listener pointer_listener = {
}; };
static void static void
seat_capabilities(void *udata, struct wl_seat *wl_seat, CSD_U32 capabilities){ seat_capabilities(void *udata, struct wl_seat *wl_seat, uint32_t capabilities){
CSD_Seat *seat = &ctx.seat; if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && ctx.wl_pointer == 0){
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer == 0){ ctx.wl_pointer = wl_seat_get_pointer(ctx.wl_seat);
seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat); wl_pointer_add_listener(ctx.wl_pointer, &pointer_listener, 0);
wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, 0);
} }
else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer != 0){ else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && ctx.wl_pointer != 0){
wl_pointer_release(seat->wl_pointer); wl_pointer_release(ctx.wl_pointer);
seat->wl_pointer = 0; ctx.wl_pointer = 0;
} }
} }
@ -188,7 +278,8 @@ static const struct wl_seat_listener seat_listener = {
static void static void
registry_global(void *udata, struct wl_registry *wl_registry, registry_global(void *udata, struct wl_registry *wl_registry,
CSD_U32 name, const char *interface, CSD_U32 version){ uint32_t name, const char *interface,
uint32_t version){
if (strcmp(interface, "wl_compositor") == 0){ if (strcmp(interface, "wl_compositor") == 0){
ctx.wl_compositor = (struct wl_compositor*) ctx.wl_compositor = (struct wl_compositor*)
wl_registry_bind(wl_registry, name, &wl_compositor_interface, wl_registry_bind(wl_registry, name, &wl_compositor_interface,
@ -215,12 +306,9 @@ registry_global(void *udata, struct wl_registry *wl_registry,
CSD_Min(version, 2)); CSD_Min(version, 2));
} }
else if (strcmp(interface, "wl_seat") == 0){ else if (strcmp(interface, "wl_seat") == 0){
CSD_Seat *seat = &ctx.seat; ctx.wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3);
if (seat->wl_seat == 0){ wl_seat_add_listener(ctx.wl_seat, &seat_listener, 0);
seat->wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3); ctx.cursor_surface = wl_compositor_create_surface(ctx.wl_compositor);
wl_seat_add_listener(seat->wl_seat, &seat_listener, 0);
seat->cursor_surface = wl_compositor_create_surface(ctx.wl_compositor);
}
} }
} }
@ -529,12 +617,9 @@ int main(){
window->dim[1] + window->csd_dim[1]); window->dim[1] + window->csd_dim[1]);
wl_egl_window_resize(ctx.main_wl_egl_window, wl_egl_window_resize(ctx.main_wl_egl_window,
window->dim[0], window->dim[1], 0, 0); window->dim[0], window->dim[1], 0, 0);
}
/* frame update and render */ /* frame update and render */
{ ctx.cursor_shape = CSD_CursorShape_Pointer;
CSD_Seat *seat = &ctx.seat;
seat->cursor_shape = CSD_CursorShape_Pointer;
csd_gtk_update_and_render(); csd_gtk_update_and_render();
} }
@ -559,18 +644,17 @@ int main(){
/* commit new cursor */ /* commit new cursor */
{ {
CSD_Seat *seat = &ctx.seat;
CSD_Window *window = &ctx.window; CSD_Window *window = &ctx.window;
struct wl_cursor *cursor = ctx.wl_cursors[seat->cursor_shape]; struct wl_cursor *cursor = ctx.wl_cursors[ctx.cursor_shape];
if (cursor != 0){ if (cursor != 0){
struct wl_cursor_image *cursor_image = cursor->images[0]; struct wl_cursor_image *cursor_image = cursor->images[0];
struct wl_buffer *cursor_buffer = wl_cursor_image_get_buffer(cursor_image); struct wl_buffer *cursor_buffer = wl_cursor_image_get_buffer(cursor_image);
wl_surface_set_buffer_scale(seat->cursor_surface, 1); wl_surface_set_buffer_scale(ctx.cursor_surface, 1);
wl_surface_attach(seat->cursor_surface, cursor_buffer, 0, 0); wl_surface_attach(ctx.cursor_surface, cursor_buffer, 0, 0);
wl_surface_damage_buffer(seat->cursor_surface, 0, 0, wl_surface_damage_buffer(ctx.cursor_surface, 0, 0,
cursor_image->width, cursor_image->height); cursor_image->width, cursor_image->height);
wl_surface_commit(seat->cursor_surface); wl_surface_commit(ctx.cursor_surface);
wl_pointer_set_cursor(seat->wl_pointer, seat->serial, seat->cursor_surface, wl_pointer_set_cursor(ctx.wl_pointer, window->serial, ctx.cursor_surface,
cursor_image->hotspot_x, cursor_image->hotspot_y); cursor_image->hotspot_x, cursor_image->hotspot_y);
} }
} }
@ -1028,37 +1112,44 @@ csd_gtk__widget_from_name(GtkWidget *root, char *name){
static void static void
csd_gtk_update_and_render(void){ csd_gtk_update_and_render(void){
CSD_Seat *seat = &ctx.seat;
CSD_Window *window = &ctx.window; CSD_Window *window = &ctx.window;
CSD_GTK_Window *gtk_window = &ctx.gtk_window; CSD_GTK_Window *gtk_window = &ctx.gtk_window;
/* determine cursor location information */ if (window->control_flags & CSD_WindowControlFlag_Resize){
enum{ static const CSD_CursorShape cursor_box[] = {
LOCATION_NULL, LOCATION_SHADOW, LOCATION_TITLEBAR, CSD_CursorShape_Resize_TopLeft, CSD_CursorShape_Resize_Top, CSD_CursorShape_Resize_TopRight,
}; CSD_CursorShape_Resize_Left, CSD_CursorShape_Pointer, CSD_CursorShape_Resize_Right,
CSD_U32 cursor_loc = LOCATION_NULL; CSD_CursorShape_Resize_BottomLeft, CSD_CursorShape_Resize_Bottom, CSD_CursorShape_Resize_BottomRight,
CSD_S32 cursor_shadow_loc = 0; };
{
{ static const enum xdg_toplevel_resize_edge xedge_box[] = {
CSD_S32 l = (seat->hover_p[0] < 0); XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT,
CSD_S32 r = (!l && seat->hover_p[0] >= window->dim[0]); XDG_TOPLEVEL_RESIZE_EDGE_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_NONE, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
CSD_S32 t = (seat->hover_p[1] < -window->csd_frame.border[1][0]); XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT,
CSD_S32 b = (!t && seat->hover_p[1] >= window->dim[1]); };
cursor_shadow_loc = 3*(b - t) + (r - l);
} int l = (ctx.hover_p[0] < 0);
if (cursor_shadow_loc != 0){ int r = (!l && ctx.hover_p[0] >= window->dim[0]);
cursor_loc = LOCATION_SHADOW; int t = (ctx.hover_p[1] < -window->csd_frame.border[1][0]);
} int b = (!t && ctx.hover_p[1] >= window->dim[1]);
else if (seat->hover_p[1] < 0){ int loc = 3*(b - t) + (r - l);
cursor_loc = LOCATION_TITLEBAR; ctx.cursor_shape = cursor_box[4 + loc];
if (gtk_window->button == BTN_LEFT){
gtk_window->button = 0;
if (loc != 0){
xdg_toplevel_resize(window->main_xdg_toplevel, ctx.wl_seat,
window->serial, xedge_box[4 + loc]);
}
else if (ctx.hover_p[1] < 0){
xdg_toplevel_move(window->main_xdg_toplevel, ctx.wl_seat, window->serial);
}
} }
} }
/* draw shadow */
{ {
CSD_SubSurface *subsurface = &gtk_window->shadow; CSD_SubSurface *subsurface = &gtk_window->shadow;
CSD_S32 shadow_dim[2]; int32_t shadow_dim[2];
shadow_dim[0] = window->dim[0] + 2*SHADOW_MARGIN; shadow_dim[0] = window->dim[0] + 2*SHADOW_MARGIN;
shadow_dim[1] = (window->dim[1] + 2*SHADOW_MARGIN + shadow_dim[1] = (window->dim[1] + 2*SHADOW_MARGIN +
window->csd_frame.border[1][0]); window->csd_frame.border[1][0]);
@ -1098,30 +1189,10 @@ csd_gtk_update_and_render(void){
csd_subsurface_commit(subsurface); csd_subsurface_commit(subsurface);
} }
/* setup buttons */
enum{
HEADER_BUTTON_NULL,
HEADER_BUTTON_MIN, HEADER_BUTTON_MAX, HEADER_BUTTON_CLOSE,
HEADER_BUTTON_COUNT
};
static char* header_button_name[] = {
0, ".minimize", ".maximize", ".close"
};
CSD_B32 header_button_active[] = {
/*NULL*/ 0,
/*MIN*/ (window->control_flags & CSD_WindowControlFlag_Min),
/*MAX*/ ((window->control_flags & CSD_WindowControlFlag_Max) &&
(window->control_flags & CSD_WindowControlFlag_Resize)),
/*CLOSE*/ (window->control_flags & CSD_WindowControlFlag_Close)
};
CSD_U32 header_button_hover = 0;
/* draw frame */
{ {
CSD_SubSurface *subsurface = &gtk_window->titlebar; CSD_SubSurface *subsurface = &gtk_window->titlebar;
CSD_S32 title_dim[2]; int32_t title_dim[2];
title_dim[0] = window->dim[0]; title_dim[0] = window->dim[0];
title_dim[1] = window->csd_frame.border[1][0]; title_dim[1] = window->csd_frame.border[1][0];
@ -1156,14 +1227,14 @@ csd_gtk_update_and_render(void){
} }
{ {
CSD_S32 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, title_dim[0]); int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, title_dim[0]);
cairo_surface_t *cr_surface = cairo_surface_t *cr_surface =
cairo_image_surface_create_for_data(subsurface->data, CAIRO_FORMAT_ARGB32, cairo_image_surface_create_for_data(subsurface->data, CAIRO_FORMAT_ARGB32,
title_dim[0], title_dim[1], stride); title_dim[0], title_dim[1], stride);
cairo_t *cr = cairo_create(cr_surface); cairo_t *cr = cairo_create(cr_surface);
cairo_surface_set_device_scale(cr_surface, 1, 1); cairo_surface_set_device_scale(cr_surface, 1, 1);
/* draw background */ /* background */
{ {
GtkAllocation allocation; GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(gtk_window->header), &allocation); gtk_widget_get_allocation(GTK_WIDGET(gtk_window->header), &allocation);
@ -1173,7 +1244,7 @@ csd_gtk_update_and_render(void){
allocation.width, allocation.height); allocation.width, allocation.height);
} }
/* draw title */ /* title */
{ {
GtkWidget *label_title = GtkWidget *label_title =
csd_gtk__widget_from_name(gtk_window->header, "label.title:"); csd_gtk__widget_from_name(gtk_window->header, "label.title:");
@ -1191,122 +1262,138 @@ csd_gtk_update_and_render(void){
cairo_surface_destroy(cr_label_surface); cairo_surface_destroy(cr_label_surface);
} }
/* draw buttons */ /* buttons */
for (CSD_U32 i = 1; i < HEADER_BUTTON_COUNT; i += 1){ uint32_t buttons[3] = {0};
if (header_button_active[i]){ int button_count = 0;
char *icon_name = ""; if (window->control_flags & CSD_WindowControlFlag_Min){
switch (i){ buttons[button_count] = 0;
case HEADER_BUTTON_MIN: { button_count += 1;
icon_name = "window-minimize-symbolic"; }
}break; if ((window->control_flags & CSD_WindowControlFlag_Max) &&
case HEADER_BUTTON_MAX: { (window->control_flags & CSD_WindowControlFlag_Resize)){
icon_name = ((window->config.flags & CSD_WindowFlag_IsMax) ? buttons[button_count] = 1;
button_count += 1;
}
if (window->control_flags & CSD_WindowControlFlag_Close){
buttons[button_count] = 2;
button_count += 1;
}
for (int i = 0; i < button_count; i += 1){
CSD_U32 button_code = buttons[i];
char *button_name = "";
char *icon_name = "";
switch (button_code){
case 0: {
button_name = ".minimize";
icon_name = "window-minimize-symbolic";
}break;
case 1: {
button_name = ".maximize";
icon_name = ((window->config.flags & CSD_WindowFlag_IsMax) ?
"window-restore-symbolic" : "window-maximize-symbolic"); "window-restore-symbolic" : "window-maximize-symbolic");
}break; }break;
case HEADER_BUTTON_CLOSE: { case 2: {
icon_name = "window-close-symbolic"; button_name = ".close";
}break; icon_name = "window-close-symbolic";
}break;
}
GtkWidget *button_widget =
csd_gtk__widget_from_name(gtk_window->header, button_name);
if (button_widget != 0){
GtkStyleContext *style = gtk_widget_get_style_context(button_widget);
/* change style based on window state and focus */
GtkStateFlags style_state = 0;
if (!(window->config.flags & CSD_WindowFlag_IsActivated)){
style_state |= GTK_STATE_FLAG_BACKDROP;
}
if (gtk_window->hover_button_code == button_code){
style_state |= GTK_STATE_FLAG_PRELIGHT;
if (gtk_window->active_button_code == button_code){
style_state |= GTK_STATE_FLAG_ACTIVE;
}
} }
GtkWidget *widget = /* background */
csd_gtk__widget_from_name(gtk_window->header, header_button_name[i]); GtkAllocation allocation;
gtk_widget_get_clip(button_widget, &allocation);
if (widget != 0){ gtk_style_context_save(style);
/* layout */ gtk_style_context_set_state(style, style_state);
GtkAllocation rect; gtk_render_background(style, cr, allocation.x, allocation.y,
gtk_widget_get_clip(widget, &rect); allocation.width, allocation.height);
gtk_render_frame(style, cr, allocation.x, allocation.y,
allocation.width, allocation.height);
gtk_style_context_restore(style);
/* check pointer hover */ /* get scale */
CSD_B32 is_hovered = 0; double sx, sy;
{ cairo_surface_get_device_scale(cr_surface, &sx, &sy);
CSD_S32 x0 = rect.x; int scale = (sx + sy)/2.0;
CSD_S32 y0 = rect.y - title_dim[1];
CSD_S32 x1 = rect.x + rect.width;
CSD_S32 y1 = rect.y + rect.height - title_dim[1];
if (x0 <= seat->hover_p[0] && seat->hover_p[0] < x1 &&
y0 <= seat->hover_p[1] && seat->hover_p[1] < y1){
header_button_hover = i;
is_hovered = 1;
}
}
/* change style based on window state and focus */ /* get original icon dimensions */
GtkStyleContext *style = gtk_widget_get_style_context(widget); GtkWidget *icon_widget = gtk_bin_get_child(GTK_BIN(button_widget));
GtkStateFlags style_state = 0;
if (!(window->config.flags & CSD_WindowFlag_IsActivated)){
style_state |= GTK_STATE_FLAG_BACKDROP;
}
if (is_hovered){
style_state |= GTK_STATE_FLAG_PRELIGHT;
if (i == gtk_window->active_header_button){
style_state |= GTK_STATE_FLAG_ACTIVE;
}
}
/* background */ /* icon info */
gtk_style_context_save(style); gint icon_width, icon_height;
gtk_style_context_set_state(style, style_state); if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)){
gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); icon_width = 16;
gtk_render_frame(style, cr, rect.x, rect.y, rect.width, rect.height); icon_height = 16;
gtk_style_context_restore(style);
/* get scale */
double sx, sy;
cairo_surface_get_device_scale(cr_surface, &sx, &sy);
int scale = (sx + sy)/2.0;
/* get original icon dimensions */
GtkWidget *icon_widget = gtk_bin_get_child(GTK_BIN(widget));
/* icon info */
gint icon_width, icon_height;
if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)){
icon_width = 16;
icon_height = 16;
}
GtkIconInfo* icon_info =
gtk_icon_theme_lookup_icon_for_scale(gtk_icon_theme_get_default(),
icon_name, icon_width, scale, 0);
/* icon pixel buffer*/
gtk_style_context_save(style);
gtk_style_context_set_state(style, style_state);
GdkPixbuf *icon_pixbuf = gtk_icon_info_load_symbolic_for_context(icon_info, style, 0, 0);
cairo_surface_t *icon_surface = gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, scale, 0);
gtk_style_context_restore(style);
/* dimensions and position */
gint width = 0;
gint height = 0;
gtk_style_context_get(style,
gtk_style_context_get_state(style),
"min-width", &width,
"min-height", &height, NULL);
width = CSD_ClampBot(width, icon_width);
height = CSD_ClampBot(height, icon_height);
GtkBorder border;
gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border);
GtkBorder padding;
gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding);
gint left = border.left + padding.left;
gint right = border.right + padding.right;
gint top = border.top + padding.top;
gint bottom = border.bottom + padding.bottom;
width += left + right;
height += top + bottom;
gtk_render_icon_surface(gtk_widget_get_style_context(icon_widget),
cr, icon_surface,
rect.x + (width - icon_width)/2,
rect.y + (height - icon_height)/2);
cairo_paint(cr);
cairo_surface_destroy(icon_surface);
g_object_unref(icon_pixbuf);
} }
GtkIconInfo* icon_info =
gtk_icon_theme_lookup_icon_for_scale(gtk_icon_theme_get_default(),
icon_name, icon_width, scale, 0);
/* icon pixel buffer*/
gtk_style_context_save(style);
gtk_style_context_set_state(style, style_state);
GdkPixbuf *icon_pixbuf = gtk_icon_info_load_symbolic_for_context(icon_info, style, 0, 0);
cairo_surface_t *icon_surface = gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, scale, 0);
gtk_style_context_restore(style);
/* dimensions and position */
gint width = 0;
gint height = 0;
gtk_style_context_get(style,
gtk_style_context_get_state(style),
"min-width", &width,
"min-height", &height, NULL);
width = CSD_ClampBot(width, icon_width);
height = CSD_ClampBot(height, icon_height);
gint left = 0;
gint top = 0;
gint right = 0;
gint bottom = 0;
GtkBorder border;
gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border);
left += border.left;
right += border.right;
top += border.top;
bottom += border.bottom;
GtkBorder padding;
gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding);
left += padding.left;
right += padding.right;
top += padding.top;
bottom += padding.bottom;
width += left + right;
height += top + bottom;
gtk_render_icon_surface(gtk_widget_get_style_context(icon_widget),
cr, icon_surface,
allocation.x + (width - icon_width)/2,
allocation.y + (height - icon_height)/2);
cairo_paint(cr);
cairo_surface_destroy(icon_surface);
g_object_unref(icon_pixbuf);
} }
} }
@ -1317,62 +1404,6 @@ csd_gtk_update_and_render(void){
csd_subsurface_set_position(subsurface, 0, -window->csd_frame.border[1][0]); csd_subsurface_set_position(subsurface, 0, -window->csd_frame.border[1][0]);
csd_subsurface_commit(subsurface); csd_subsurface_commit(subsurface);
} }
/* process events */
if (ctx.has_event){
/* handle left-button press */
if (ctx.event_button == BTN_LEFT &&
ctx.event_button_state == 1){
switch (cursor_loc){
default: case LOCATION_NULL: break;
case LOCATION_SHADOW: {
static const enum xdg_toplevel_resize_edge xedge_box[] = {
XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT,
XDG_TOPLEVEL_RESIZE_EDGE_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_NONE, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT,
};
xdg_toplevel_resize(window->main_xdg_toplevel, seat->wl_seat,
seat->serial, xedge_box[4 + cursor_shadow_loc]);
ctx.has_event = 0;
}break;
case LOCATION_TITLEBAR: {
if (header_button_hover == 0){
xdg_toplevel_move(window->main_xdg_toplevel, seat->wl_seat, seat->serial);
}
else{
gtk_window->active_header_button = header_button_hover;
}
ctx.has_event = 0;
}break;
}
}
/* handle left-button release */
if (ctx.event_button == BTN_LEFT &&
ctx.event_button_state == 0){
if (gtk_window->active_header_button != 0 &&
gtk_window->active_header_button == header_button_hover){
// activate button effect here
}
gtk_window->active_header_button = 0;
}
}
/* set cursor shape */
if (window->control_flags & CSD_WindowControlFlag_Resize){
static const CSD_CursorShape cursor_box[] = {
CSD_CursorShape_Resize_TopLeft, CSD_CursorShape_Resize_Top, CSD_CursorShape_Resize_TopRight,
CSD_CursorShape_Resize_Left, CSD_CursorShape_Pointer, CSD_CursorShape_Resize_Right,
CSD_CursorShape_Resize_BottomLeft, CSD_CursorShape_Resize_Bottom, CSD_CursorShape_Resize_BottomRight,
};
seat->cursor_shape = cursor_box[4 + cursor_shadow_loc];
}
else{
seat->cursor_shape = CSD_CursorShape_Pointer;
}
} }
/* cairo shadow rendering */ /* cairo shadow rendering */

View File

@ -86,7 +86,7 @@ typedef struct CSD_Config{
} CSD_Config; } CSD_Config;
typedef struct CSD_Frame{ typedef struct CSD_Frame{
CSD_S32 border[2][2]; CSD_S32 border[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max
CSD_S32 minbox[2]; CSD_S32 minbox[2];
} CSD_Frame; } CSD_Frame;
@ -111,6 +111,7 @@ typedef struct CSD_Window{
CSD_Config config; CSD_Config config;
CSD_Config config_staged; CSD_Config config_staged;
CSD_U32 serial;
CSD_Frame csd_frame; CSD_Frame csd_frame;
CSD_S32 csd_dim[2]; CSD_S32 csd_dim[2];
@ -119,18 +120,6 @@ typedef struct CSD_Window{
CSD_S32 dim[2]; CSD_S32 dim[2];
} CSD_Window; } CSD_Window;
typedef struct CSD_Seat{
struct wl_seat *wl_seat;
struct wl_pointer *wl_pointer;
struct wl_surface *cursor_surface;
CSD_CursorShape cursor_shape;
struct wl_surface *hover_surface;
CSD_S32 hover_p[2];
CSD_U32 serial;
} CSD_Seat;
/* csd helpers */ /* csd helpers */
static CSD_SubSurface csd_subsurface_new(void); static CSD_SubSurface csd_subsurface_new(void);
@ -167,14 +156,17 @@ typedef struct CSD_GTK_Ctx{
} CSD_GTK_Ctx; } CSD_GTK_Ctx;
typedef struct CSD_GTK_Window{ typedef struct CSD_GTK_Window{
CSD_U32 button;
CSD_S32 double_click_time_ms;
CSD_SubSurface titlebar; CSD_SubSurface titlebar;
CSD_SubSurface shadow; CSD_SubSurface shadow;
GtkWidget *window; GtkWidget *window;
GtkWidget *header; GtkWidget *header;
CSD_S32 double_click_time_ms; CSD_U32 hover_button_code;
CSD_U32 active_header_button; CSD_U32 active_button_code;
} CSD_GTK_Window; } CSD_GTK_Window;
/* csd gtk implementation */ /* csd gtk implementation */
@ -184,6 +176,14 @@ static void csd_gtk_window_init(void);
static CSD_Frame csd_gtk_calculate_frame(void); static CSD_Frame csd_gtk_calculate_frame(void);
static void csd_gtk_update_and_render(void); static void csd_gtk_update_and_render(void);
static void csd_gtk_render(void);
#if 0
static CSD_B32 csd_gtk_pointer_enter(CSD_GTK_Window *gtk_window, uint32_t serial, struct wl_surface *surface, wl_fixed_t fx, wl_fixed_t fy);
static CSD_B32 csd_gtk_pointer_leave(CSD_GTK_Window *gtk_window, uint32_t serial, struct wl_surface *surface);
static CSD_B32 csd_gtk_pointer_motion(CSD_GTK_Window *gtk_window, uint32_t time, wl_fixed_t fx, wl_fixed_t fy);
static CSD_B32 csd_gtk_pointer_button(CSD_GTK_Window *gtk_window, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
#endif
/* csd gtk cairo shadow rendering */ /* csd gtk cairo shadow rendering */
@ -196,13 +196,9 @@ static void csd_gtk_render_shadow(cairo_t *cr, cairo_surface_t *surface,
/* example */ /* example */
typedef struct Ctx{ typedef struct Ctx{
/* the rest */ /* "application variables" */
CSD_B32 close_signal; CSD_B32 close_signal;
CSD_B32 has_event;
CSD_U32 event_button;
CSD_U32 event_button_state;
/* globals: desktop settings */ /* globals: desktop settings */
CSD_ColorScheme color_scheme; CSD_ColorScheme color_scheme;
CSD_CursorTheme cursor_theme; CSD_CursorTheme cursor_theme;
@ -226,8 +222,15 @@ typedef struct Ctx{
/* globals: gtk */ /* globals: gtk */
CSD_GTK_Ctx gtk_ctx; CSD_GTK_Ctx gtk_ctx;
/* per-seat */ /* per-seat: wayland */
CSD_Seat seat; struct wl_seat *wl_seat;
struct wl_pointer *wl_pointer;
struct wl_surface *cursor_surface;
struct wl_surface *hover_surface;
CSD_S32 hover_p[2];
CSD_CursorShape cursor_shape;
/* per-window: egl */ /* per-window: egl */
struct wl_egl_window *main_wl_egl_window; struct wl_egl_window *main_wl_egl_window;