mirror of https://github.com/fltk/fltk
Update libdecor to upstream commit 09875530 dated March 3, 2024
This commit is contained in:
parent
38af0c823b
commit
70a9c4d407
|
@ -23,14 +23,14 @@ The nanosvg library is not affected.
|
|||
|
||||
\section bundled-status Current status
|
||||
\code
|
||||
Current versions of bundled libraries (as of February 17, 2024):
|
||||
Current versions of bundled libraries (as of March 12, 2024):
|
||||
Library Version/git commit Release date FLTK Version
|
||||
--------------------------------------------------------------------------
|
||||
jpeg jpeg-9f 2024-01-14 1.4.0
|
||||
nanosvg 7aeda550a8 [1] 2023-12-02 1.4.0
|
||||
png libpng-1.6.42 2024-01-29 1.4.0
|
||||
zlib zlib-1.3.1 2024-01-22 1.4.0
|
||||
libdecor 7807ae34 [2] 2024-01-15 1.4.0
|
||||
libdecor 09875530 [2] 2024-03-03 1.4.0
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Previous versions of bundled libraries (FLTK 1.3.x):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// Interface with the libdecor library for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2022-2023 by Bill Spitzak and others.
|
||||
// Copyright 2022-2024 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <string.h>
|
||||
#include "../src/libdecor.h"
|
||||
#include <pango/pangocairo.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifndef HAVE_GTK
|
||||
# define HAVE_GTK 0
|
||||
|
@ -137,25 +138,6 @@ struct libdecor_frame_cairo {
|
|||
|
||||
/* Definitions derived from libdecor-gtk.c */
|
||||
|
||||
struct libdecor_plugin_gtk {
|
||||
struct libdecor_plugin plugin;
|
||||
struct wl_callback *globals_callback;
|
||||
struct wl_callback *globals_callback_shm;
|
||||
struct libdecor *context;
|
||||
struct wl_registry *wl_registry;
|
||||
struct wl_subcompositor *wl_subcompositor;
|
||||
struct wl_compositor *wl_compositor;
|
||||
struct wl_shm *wl_shm;
|
||||
struct wl_callback *shm_callback;
|
||||
bool has_argb;
|
||||
struct wl_list visible_frame_list;
|
||||
struct wl_list seat_list;
|
||||
struct wl_list output_list;
|
||||
char *cursor_theme_name;
|
||||
int cursor_size;
|
||||
int double_click_time_ms;
|
||||
};
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
enum header_element { HEADER_NONE }; /* details are not needed */
|
||||
|
||||
|
@ -201,6 +183,15 @@ struct libdecor_frame_gtk {
|
|||
struct header_element_data hdr_focus;
|
||||
cairo_surface_t *shadow_blur;
|
||||
struct wl_list link;
|
||||
struct {
|
||||
enum titlebar_gesture_state {TITLEBAR_GESTURE_STATE_INIT} state;
|
||||
int button_pressed_count;
|
||||
uint32_t first_pressed_button;
|
||||
uint32_t first_pressed_time;
|
||||
double pressed_x;
|
||||
double pressed_y;
|
||||
uint32_t pressed_serial;
|
||||
} titlebar_gesture;
|
||||
};
|
||||
|
||||
#endif // USE_SYSTEM_LIBDECOR || !HAVE_GTK
|
||||
|
@ -310,9 +301,27 @@ unsigned char *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame,
|
|||
}
|
||||
|
||||
|
||||
struct libdecor { // copied from libdecor.c
|
||||
// When the libdecor version after 0.2.2 will be released, support of older versions
|
||||
// will be removed from FLTK. LIBDECOR_MR131 stuff also will be removed.
|
||||
struct libdecor_022 { // for libdecor versions ≤ 0.2.2
|
||||
int ref_count;
|
||||
struct libdecor_interface *iface;
|
||||
const struct libdecor_interface *iface;
|
||||
struct libdecor_plugin *plugin;
|
||||
bool plugin_ready;
|
||||
struct wl_display *wl_display;
|
||||
struct wl_registry *wl_registry;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zxdg_decoration_manager_v1 *decoration_manager;
|
||||
struct wl_callback *init_callback;
|
||||
bool init_done;
|
||||
bool has_error;
|
||||
struct wl_list frames;
|
||||
};
|
||||
|
||||
struct libdecor { // copied from libdecor.c, for libdecor versions > 0.2.2
|
||||
int ref_count;
|
||||
const struct libdecor_interface *iface;
|
||||
void *user_data; // added after libdecor version 0.2.2
|
||||
struct libdecor_plugin *plugin;
|
||||
bool plugin_ready;
|
||||
struct wl_display *wl_display;
|
||||
|
@ -329,9 +338,18 @@ struct libdecor { // copied from libdecor.c
|
|||
/* Returns whether surface is a GTK-titlebar created by libdecor-gtk */
|
||||
bool fl_is_surface_gtk_titlebar(struct wl_surface *surface, struct libdecor *context) {
|
||||
if (!context || get_plugin_kind(NULL) != GTK3) return false;
|
||||
static void *new_symbol = NULL;
|
||||
static bool first = true;
|
||||
if (first) {
|
||||
first = false;
|
||||
// new_symbol is NULL for libdecor versions ≤ 0.2.2
|
||||
new_symbol = dlsym(RTLD_DEFAULT, "libdecor_frame_get_user_data");
|
||||
}
|
||||
struct wl_list *frames_addr = (new_symbol ? &context->frames :
|
||||
&(((struct libdecor_022*)context)->frames) );
|
||||
// loop over all decorations created by libdecor-gtk
|
||||
struct libdecor_frame *frame;
|
||||
wl_list_for_each(frame, &context->frames, link) {
|
||||
wl_list_for_each(frame, frames_addr, link) {
|
||||
struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk*)frame;
|
||||
if (frame_gtk->headerbar.wl_surface == surface) return true;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ LIBDECOR_EXPORT void libdecor_frame_set_minimized(struct libdecor_frame *frame)
|
|||
so a plugin may be loaded that way only if FLTK was built with FLTK_USE_SYSTEM_LIBDECOR turned ON.
|
||||
|
||||
*/
|
||||
LIBDECOR_EXPORT struct libdecor *libdecor_new(struct wl_display *wl_display, struct libdecor_interface *iface)
|
||||
LIBDECOR_EXPORT struct libdecor *libdecor_new(struct wl_display *wl_display, const struct libdecor_interface *iface)
|
||||
{
|
||||
struct libdecor *context;
|
||||
context = zalloc(sizeof *context);
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
struct libdecor {
|
||||
int ref_count;
|
||||
|
||||
struct libdecor_interface *iface;
|
||||
const struct libdecor_interface *iface;
|
||||
void *user_data;
|
||||
|
||||
struct libdecor_plugin *plugin;
|
||||
bool plugin_ready;
|
||||
|
@ -100,7 +101,7 @@ struct libdecor_frame_private {
|
|||
|
||||
struct wl_surface *wl_surface;
|
||||
|
||||
struct libdecor_frame_interface *iface;
|
||||
const struct libdecor_frame_interface *iface;
|
||||
void *user_data;
|
||||
|
||||
struct xdg_surface *xdg_surface;
|
||||
|
@ -127,6 +128,8 @@ struct libdecor_frame_private {
|
|||
|
||||
enum libdecor_capabilities capabilities;
|
||||
|
||||
enum libdecor_wm_capabilities wm_capabilities;
|
||||
|
||||
/* original limits for interactive resize */
|
||||
struct libdecor_limits interactive_limits;
|
||||
|
||||
|
@ -396,6 +399,9 @@ parse_states(struct wl_array *states)
|
|||
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
|
||||
pending_state |= LIBDECOR_WINDOW_STATE_TILED_BOTTOM;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_RESIZING:
|
||||
pending_state |= LIBDECOR_WINDOW_STATE_RESIZING;
|
||||
break;
|
||||
#ifdef HAVE_XDG_SHELL_V6
|
||||
case XDG_TOPLEVEL_STATE_SUSPENDED:
|
||||
pending_state |= LIBDECOR_WINDOW_STATE_SUSPENDED;
|
||||
|
@ -452,10 +458,34 @@ xdg_toplevel_configure_bounds(void *data,
|
|||
}
|
||||
|
||||
static void
|
||||
xdg_toplevel_wm_capabilities(void *data,
|
||||
xdg_toplevel_wm_capabilities(void *user_data,
|
||||
struct xdg_toplevel *xdg_toplevel,
|
||||
struct wl_array *capabilities)
|
||||
{
|
||||
struct libdecor_frame *frame = user_data;
|
||||
struct libdecor_frame_private *frame_priv = frame->priv;
|
||||
enum xdg_toplevel_wm_capabilities *wm_cap;
|
||||
|
||||
frame_priv->wm_capabilities = 0;
|
||||
|
||||
wl_array_for_each(wm_cap, capabilities) {
|
||||
switch (*wm_cap) {
|
||||
case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU:
|
||||
frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU;
|
||||
break;
|
||||
case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE:
|
||||
frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE;
|
||||
break;
|
||||
case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN:
|
||||
frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN;
|
||||
break;
|
||||
case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE:
|
||||
frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -546,7 +576,7 @@ init_shell_surface(struct libdecor_frame *frame)
|
|||
LIBDECOR_EXPORT struct libdecor_frame *
|
||||
libdecor_decorate(struct libdecor *context,
|
||||
struct wl_surface *wl_surface,
|
||||
struct libdecor_frame_interface *iface,
|
||||
const struct libdecor_frame_interface *iface,
|
||||
void *user_data)
|
||||
{
|
||||
struct libdecor_plugin *plugin = context->plugin;
|
||||
|
@ -569,6 +599,10 @@ libdecor_decorate(struct libdecor *context,
|
|||
frame_priv->wl_surface = wl_surface;
|
||||
frame_priv->iface = iface;
|
||||
frame_priv->user_data = user_data;
|
||||
frame_priv->wm_capabilities = LIBDECOR_WM_CAPABILITIES_WINDOW_MENU |
|
||||
LIBDECOR_WM_CAPABILITIES_MAXIMIZE |
|
||||
LIBDECOR_WM_CAPABILITIES_FULLSCREEN |
|
||||
LIBDECOR_WM_CAPABILITIES_MINIMIZE;
|
||||
|
||||
wl_list_insert(&context->frames, &frame->link);
|
||||
|
||||
|
@ -628,6 +662,18 @@ libdecor_frame_unref(struct libdecor_frame *frame)
|
|||
}
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT void *
|
||||
libdecor_frame_get_user_data(struct libdecor_frame *frame)
|
||||
{
|
||||
return frame->priv->user_data;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT void
|
||||
libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data)
|
||||
{
|
||||
frame->priv->user_data = user_data;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT void
|
||||
libdecor_frame_set_visibility(struct libdecor_frame *frame,
|
||||
bool visible)
|
||||
|
@ -1235,6 +1281,14 @@ libdecor_frame_get_window_state(struct libdecor_frame *frame)
|
|||
return frame_priv->window_state;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT enum libdecor_wm_capabilities
|
||||
libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame)
|
||||
{
|
||||
struct libdecor_frame_private *frame_priv = frame->priv;
|
||||
|
||||
return frame_priv->wm_capabilities;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT int
|
||||
libdecor_plugin_init(struct libdecor_plugin *plugin,
|
||||
struct libdecor *context,
|
||||
|
@ -1624,6 +1678,18 @@ retry_next:
|
|||
return 0;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT void *
|
||||
libdecor_get_user_data(struct libdecor *context)
|
||||
{
|
||||
return context->user_data;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT void
|
||||
libdecor_set_user_data(struct libdecor *context, void *user_data)
|
||||
{
|
||||
context->user_data = user_data;
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT int
|
||||
libdecor_get_fd(struct libdecor *context)
|
||||
{
|
||||
|
@ -1701,7 +1767,15 @@ libdecor_unref(struct libdecor *context)
|
|||
|
||||
LIBDECOR_EXPORT struct libdecor *
|
||||
libdecor_new(struct wl_display *wl_display,
|
||||
struct libdecor_interface *iface)
|
||||
const struct libdecor_interface *iface)
|
||||
{
|
||||
return libdecor_new_with_user_data(wl_display, iface, NULL);
|
||||
}
|
||||
|
||||
LIBDECOR_EXPORT struct libdecor *
|
||||
libdecor_new_with_user_data(struct wl_display *wl_display,
|
||||
const struct libdecor_interface *iface,
|
||||
void *user_data)
|
||||
{
|
||||
struct libdecor *context;
|
||||
|
||||
|
@ -1709,6 +1783,7 @@ libdecor_new(struct wl_display *wl_display,
|
|||
|
||||
context->ref_count = 1;
|
||||
context->iface = iface;
|
||||
context->user_data = user_data;
|
||||
context->wl_display = wl_display;
|
||||
context->wl_registry = wl_display_get_registry(wl_display);
|
||||
wl_registry_add_listener(context->wl_registry,
|
||||
|
|
|
@ -82,6 +82,7 @@ enum libdecor_window_state {
|
|||
LIBDECOR_WINDOW_STATE_TILED_TOP = 1 << 5,
|
||||
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 1 << 6,
|
||||
LIBDECOR_WINDOW_STATE_SUSPENDED = 1 << 7,
|
||||
LIBDECOR_WINDOW_STATE_RESIZING = 1 << 8,
|
||||
};
|
||||
|
||||
enum libdecor_resize_edge {
|
||||
|
@ -104,6 +105,13 @@ enum libdecor_capabilities {
|
|||
LIBDECOR_ACTION_CLOSE = 1 << 4,
|
||||
};
|
||||
|
||||
enum libdecor_wm_capabilities {
|
||||
LIBDECOR_WM_CAPABILITIES_WINDOW_MENU = 1 << 0,
|
||||
LIBDECOR_WM_CAPABILITIES_MAXIMIZE = 1 << 1,
|
||||
LIBDECOR_WM_CAPABILITIES_FULLSCREEN = 1 << 2,
|
||||
LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3
|
||||
};
|
||||
|
||||
struct libdecor_interface {
|
||||
/**
|
||||
* An error event
|
||||
|
@ -185,7 +193,27 @@ libdecor_unref(struct libdecor *context);
|
|||
*/
|
||||
struct libdecor *
|
||||
libdecor_new(struct wl_display *display,
|
||||
struct libdecor_interface *iface);
|
||||
const struct libdecor_interface *iface);
|
||||
|
||||
/**
|
||||
* Create a new libdecor context for the given wl_display and attach user data.
|
||||
*/
|
||||
struct libdecor *
|
||||
libdecor_new_with_user_data(struct wl_display *display,
|
||||
const struct libdecor_interface *iface,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Get the user data associated with this libdecor context.
|
||||
*/
|
||||
void *
|
||||
libdecor_get_user_data(struct libdecor *context);
|
||||
|
||||
/**
|
||||
* Set the user data associated with this libdecor context.
|
||||
*/
|
||||
void
|
||||
libdecor_set_user_data(struct libdecor *context, void *user_data);
|
||||
|
||||
/**
|
||||
* Get the file descriptor used by libdecor. This is similar to
|
||||
|
@ -218,7 +246,7 @@ libdecor_dispatch(struct libdecor *context,
|
|||
struct libdecor_frame *
|
||||
libdecor_decorate(struct libdecor *context,
|
||||
struct wl_surface *surface,
|
||||
struct libdecor_frame_interface *iface,
|
||||
const struct libdecor_frame_interface *iface,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
|
@ -234,6 +262,18 @@ libdecor_frame_ref(struct libdecor_frame *frame);
|
|||
void
|
||||
libdecor_frame_unref(struct libdecor_frame *frame);
|
||||
|
||||
/**
|
||||
* Get the user data associated with this libdecor frame.
|
||||
*/
|
||||
void *
|
||||
libdecor_frame_get_user_data(struct libdecor_frame *frame);
|
||||
|
||||
/**
|
||||
* Set the user data associated with this libdecor frame.
|
||||
*/
|
||||
void
|
||||
libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data);
|
||||
|
||||
/**
|
||||
* Set the visibility of the frame.
|
||||
*
|
||||
|
@ -497,6 +537,12 @@ libdecor_frame_get_xdg_surface(struct libdecor_frame *frame);
|
|||
struct xdg_toplevel *
|
||||
libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame);
|
||||
|
||||
/**
|
||||
* Get the supported window manager capabilities for the window.
|
||||
*/
|
||||
enum libdecor_wm_capabilities
|
||||
libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame);
|
||||
|
||||
/**
|
||||
* Create a new content surface state.
|
||||
*/
|
||||
|
|
|
@ -70,6 +70,13 @@ enum header_element {
|
|||
HEADER_CLOSE,
|
||||
};
|
||||
|
||||
enum titlebar_gesture_state {
|
||||
TITLEBAR_GESTURE_STATE_INIT,
|
||||
TITLEBAR_GESTURE_STATE_BUTTON_PRESSED,
|
||||
TITLEBAR_GESTURE_STATE_CONSUMED,
|
||||
TITLEBAR_GESTURE_STATE_DISCARDED,
|
||||
};
|
||||
|
||||
struct header_element_data {
|
||||
const char *name;
|
||||
enum header_element type;
|
||||
|
@ -206,7 +213,6 @@ struct seat {
|
|||
|
||||
int pointer_x, pointer_y;
|
||||
|
||||
uint32_t pointer_button_time_stamp;
|
||||
uint32_t touch_down_time_stamp;
|
||||
|
||||
uint32_t serial;
|
||||
|
@ -297,6 +303,16 @@ struct libdecor_frame_gtk {
|
|||
cairo_surface_t *shadow_blur;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
struct {
|
||||
enum titlebar_gesture_state state;
|
||||
int button_pressed_count;
|
||||
uint32_t first_pressed_button;
|
||||
uint32_t first_pressed_time;
|
||||
double pressed_x;
|
||||
double pressed_y;
|
||||
uint32_t pressed_serial;
|
||||
} titlebar_gesture;
|
||||
};
|
||||
|
||||
struct libdecor_plugin_gtk {
|
||||
|
@ -323,6 +339,7 @@ struct libdecor_plugin_gtk {
|
|||
int cursor_size;
|
||||
|
||||
int double_click_time_ms;
|
||||
int drag_threshold;
|
||||
};
|
||||
|
||||
static const char *libdecor_gtk_proxy_tag = "libdecor-gtk";
|
||||
|
@ -912,7 +929,10 @@ ensure_title_bar_surfaces(struct libdecor_frame_gtk *frame_gtk)
|
|||
|
||||
g_object_get(gtk_widget_get_settings(frame_gtk->window),
|
||||
"gtk-double-click-time",
|
||||
&frame_gtk->plugin_gtk->double_click_time_ms, NULL);
|
||||
&frame_gtk->plugin_gtk->double_click_time_ms,
|
||||
"gtk-dnd-drag-threshold",
|
||||
&frame_gtk->plugin_gtk->drag_threshold,
|
||||
NULL);
|
||||
/* set as "default" decoration */
|
||||
g_object_set(frame_gtk->header,
|
||||
"title", libdecor_frame_get_title(&frame_gtk->frame),
|
||||
|
@ -2114,6 +2134,10 @@ pointer_leave(void *data,
|
|||
|
||||
seat->pointer_focus = NULL;
|
||||
if (frame_gtk) {
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_INIT;
|
||||
frame_gtk->titlebar_gesture.first_pressed_button = 0;
|
||||
|
||||
frame_gtk->active = NULL;
|
||||
frame_gtk->hdr_focus.widget = NULL;
|
||||
frame_gtk->hdr_focus.type = HEADER_NONE;
|
||||
|
@ -2132,6 +2156,7 @@ pointer_motion(void *data,
|
|||
{
|
||||
struct seat *seat = data;
|
||||
struct libdecor_frame_gtk *frame_gtk;
|
||||
struct header_element_data new_focus;
|
||||
|
||||
if (!seat->pointer_focus || !own_surface(seat->pointer_focus))
|
||||
return;
|
||||
|
@ -2143,21 +2168,219 @@ pointer_motion(void *data,
|
|||
|
||||
frame_gtk = wl_surface_get_user_data(seat->pointer_focus);
|
||||
/* avoid warnings after decoration has been turned off */
|
||||
if (GTK_IS_WIDGET(frame_gtk->header) && frame_gtk->active->type == HEADER) {
|
||||
struct header_element_data new_focus = get_header_focus(
|
||||
GTK_HEADER_BAR(frame_gtk->header),
|
||||
seat->pointer_x, seat->pointer_y);
|
||||
/* only update if widget change so that we keep the state */
|
||||
if (frame_gtk->hdr_focus.widget != new_focus.widget) {
|
||||
frame_gtk->hdr_focus = new_focus;
|
||||
}
|
||||
frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
|
||||
/* redraw with updated button visuals */
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
} else {
|
||||
if (!GTK_IS_WIDGET(frame_gtk->header) || frame_gtk->active->type != HEADER) {
|
||||
frame_gtk->hdr_focus.type = HEADER_NONE;
|
||||
}
|
||||
|
||||
new_focus = get_header_focus(GTK_HEADER_BAR(frame_gtk->header),
|
||||
seat->pointer_x, seat->pointer_y);
|
||||
|
||||
/* only update if widget change so that we keep the state */
|
||||
if (frame_gtk->hdr_focus.widget != new_focus.widget) {
|
||||
frame_gtk->hdr_focus = new_focus;
|
||||
}
|
||||
frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
|
||||
/* redraw with updated button visuals */
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
|
||||
switch (frame_gtk->titlebar_gesture.state) {
|
||||
case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
|
||||
if (frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT) {
|
||||
if (ABS ((double) seat->pointer_x -
|
||||
(double) frame_gtk->titlebar_gesture.pressed_x) >
|
||||
frame_gtk->plugin_gtk->drag_threshold ||
|
||||
ABS ((double) seat->pointer_y -
|
||||
(double) frame_gtk->titlebar_gesture.pressed_y) >
|
||||
frame_gtk->plugin_gtk->drag_threshold) {
|
||||
libdecor_frame_move(&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
frame_gtk->titlebar_gesture.pressed_serial);
|
||||
}
|
||||
}
|
||||
case TITLEBAR_GESTURE_STATE_INIT:
|
||||
case TITLEBAR_GESTURE_STATE_CONSUMED:
|
||||
case TITLEBAR_GESTURE_STATE_DISCARDED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_button_on_shadow(struct libdecor_frame_gtk *frame_gtk,
|
||||
struct seat *seat,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE;
|
||||
|
||||
edge = component_edge(frame_gtk->active,
|
||||
seat->pointer_x,
|
||||
seat->pointer_y,
|
||||
SHADOW_MARGIN);
|
||||
|
||||
if (edge != LIBDECOR_RESIZE_EDGE_NONE && resizable(frame_gtk)) {
|
||||
libdecor_frame_resize(&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
serial,
|
||||
edge);
|
||||
}
|
||||
}
|
||||
|
||||
enum titlebar_gesture {
|
||||
TITLEBAR_GESTURE_DOUBLE_CLICK,
|
||||
TITLEBAR_GESTURE_MIDDLE_CLICK,
|
||||
TITLEBAR_GESTURE_RIGHT_CLICK,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_titlebar_gesture(struct libdecor_frame_gtk *frame_gtk,
|
||||
struct seat *seat,
|
||||
uint32_t serial,
|
||||
enum titlebar_gesture gesture)
|
||||
{
|
||||
switch (gesture) {
|
||||
case TITLEBAR_GESTURE_DOUBLE_CLICK:
|
||||
toggle_maximized(&frame_gtk->frame);
|
||||
break;
|
||||
case TITLEBAR_GESTURE_MIDDLE_CLICK:
|
||||
break;
|
||||
case TITLEBAR_GESTURE_RIGHT_CLICK:
|
||||
const int title_height = gtk_widget_get_allocated_height(frame_gtk->header);
|
||||
|
||||
libdecor_frame_show_window_menu(&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
serial,
|
||||
seat->pointer_x,
|
||||
seat->pointer_y
|
||||
-title_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_button_on_header(struct libdecor_frame_gtk *frame_gtk,
|
||||
struct seat *seat,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
switch (frame_gtk->titlebar_gesture.state) {
|
||||
case TITLEBAR_GESTURE_STATE_INIT:
|
||||
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
return;
|
||||
|
||||
if (button == BTN_RIGHT) {
|
||||
handle_titlebar_gesture(frame_gtk,
|
||||
seat,
|
||||
serial,
|
||||
TITLEBAR_GESTURE_RIGHT_CLICK);
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_CONSUMED;
|
||||
} else {
|
||||
if (button == BTN_LEFT &&
|
||||
frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT &&
|
||||
time - frame_gtk->titlebar_gesture.first_pressed_time <
|
||||
(uint32_t) frame_gtk->plugin_gtk->double_click_time_ms) {
|
||||
handle_titlebar_gesture(frame_gtk,
|
||||
seat,
|
||||
serial,
|
||||
TITLEBAR_GESTURE_DOUBLE_CLICK);
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_CONSUMED;
|
||||
} else {
|
||||
frame_gtk->titlebar_gesture.first_pressed_button = button;
|
||||
frame_gtk->titlebar_gesture.first_pressed_time = time;
|
||||
frame_gtk->titlebar_gesture.pressed_x = seat->pointer_x;
|
||||
frame_gtk->titlebar_gesture.pressed_y = seat->pointer_y;
|
||||
frame_gtk->titlebar_gesture.pressed_serial = serial;
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_BUTTON_PRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
frame_gtk->titlebar_gesture.button_pressed_count = 1;
|
||||
|
||||
switch (frame_gtk->hdr_focus.type) {
|
||||
case HEADER_MIN:
|
||||
case HEADER_MAX:
|
||||
case HEADER_CLOSE:
|
||||
frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE;
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
|
||||
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_DISCARDED;
|
||||
frame_gtk->titlebar_gesture.button_pressed_count++;
|
||||
} else {
|
||||
frame_gtk->titlebar_gesture.button_pressed_count--;
|
||||
|
||||
if (frame_gtk->titlebar_gesture.button_pressed_count == 0) {
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_INIT;
|
||||
if (frame_gtk->titlebar_gesture.first_pressed_button == button &&
|
||||
button == BTN_LEFT) {
|
||||
libdecor_frame_ref(&frame_gtk->frame);
|
||||
switch (frame_gtk->hdr_focus.type) {
|
||||
case HEADER_MIN:
|
||||
if (minimizable(frame_gtk))
|
||||
libdecor_frame_set_minimized(
|
||||
&frame_gtk->frame);
|
||||
break;
|
||||
case HEADER_MAX:
|
||||
toggle_maximized(&frame_gtk->frame);
|
||||
break;
|
||||
case HEADER_CLOSE:
|
||||
if (closeable(frame_gtk)) {
|
||||
libdecor_frame_close(
|
||||
&frame_gtk->frame);
|
||||
seat->pointer_focus = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
|
||||
if (GTK_IS_WIDGET(frame_gtk->header)) {
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
}
|
||||
libdecor_frame_unref(&frame_gtk->frame);
|
||||
}
|
||||
} else {
|
||||
frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
|
||||
if (GTK_IS_WIDGET(frame_gtk->header)) {
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case TITLEBAR_GESTURE_STATE_CONSUMED:
|
||||
case TITLEBAR_GESTURE_STATE_DISCARDED:
|
||||
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
frame_gtk->titlebar_gesture.button_pressed_count++;
|
||||
} else {
|
||||
frame_gtk->titlebar_gesture.button_pressed_count--;
|
||||
if (frame_gtk->titlebar_gesture.button_pressed_count == 0) {
|
||||
frame_gtk->titlebar_gesture.state =
|
||||
TITLEBAR_GESTURE_STATE_INIT;
|
||||
frame_gtk->titlebar_gesture.first_pressed_button = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2178,98 +2401,14 @@ pointer_button(void *data,
|
|||
if (!frame_gtk)
|
||||
return;
|
||||
|
||||
if (button == BTN_LEFT) {
|
||||
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
enum libdecor_resize_edge edge =
|
||||
LIBDECOR_RESIZE_EDGE_NONE;
|
||||
switch (frame_gtk->active->type) {
|
||||
case SHADOW:
|
||||
edge = component_edge(frame_gtk->active,
|
||||
seat->pointer_x,
|
||||
seat->pointer_y,
|
||||
SHADOW_MARGIN);
|
||||
break;
|
||||
case HEADER:
|
||||
switch (frame_gtk->hdr_focus.type) {
|
||||
case HEADER_MIN:
|
||||
case HEADER_MAX:
|
||||
case HEADER_CLOSE:
|
||||
frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE;
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
break;
|
||||
default:
|
||||
if (time-seat->pointer_button_time_stamp <
|
||||
(uint32_t)frame_gtk->plugin_gtk->double_click_time_ms) {
|
||||
toggle_maximized(&frame_gtk->frame);
|
||||
}
|
||||
else if (moveable(frame_gtk)) {
|
||||
seat->pointer_button_time_stamp = time;
|
||||
libdecor_frame_move(&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
serial);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (edge != LIBDECOR_RESIZE_EDGE_NONE &&
|
||||
resizable(frame_gtk)) {
|
||||
libdecor_frame_resize(
|
||||
&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
serial,
|
||||
edge);
|
||||
}
|
||||
}
|
||||
else if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
||||
switch (frame_gtk->active->type) {
|
||||
case HEADER:
|
||||
libdecor_frame_ref(&frame_gtk->frame);
|
||||
switch (frame_gtk->hdr_focus.type) {
|
||||
case HEADER_MIN:
|
||||
if (minimizable(frame_gtk))
|
||||
libdecor_frame_set_minimized(
|
||||
&frame_gtk->frame);
|
||||
break;
|
||||
case HEADER_MAX:
|
||||
toggle_maximized(&frame_gtk->frame);
|
||||
break;
|
||||
case HEADER_CLOSE:
|
||||
if (closeable(frame_gtk)) {
|
||||
libdecor_frame_close(
|
||||
&frame_gtk->frame);
|
||||
seat->pointer_focus = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* unset active/clicked state once released */
|
||||
frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
|
||||
if (GTK_IS_WIDGET(frame_gtk->header)) {
|
||||
draw_title_bar(frame_gtk);
|
||||
libdecor_frame_toplevel_commit(&frame_gtk->frame);
|
||||
}
|
||||
libdecor_frame_unref(&frame_gtk->frame);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (button == BTN_RIGHT &&
|
||||
state == WL_POINTER_BUTTON_STATE_PRESSED &&
|
||||
seat->pointer_focus == frame_gtk->headerbar.wl_surface) {
|
||||
const int title_height = gtk_widget_get_allocated_height(frame_gtk->header);
|
||||
libdecor_frame_show_window_menu(&frame_gtk->frame,
|
||||
seat->wl_seat,
|
||||
serial,
|
||||
seat->pointer_x,
|
||||
seat->pointer_y
|
||||
-title_height);
|
||||
switch (frame_gtk->active->type) {
|
||||
case SHADOW:
|
||||
handle_button_on_shadow (frame_gtk, seat, serial, time, button, state);
|
||||
break;
|
||||
case HEADER:
|
||||
handle_button_on_header (frame_gtk, seat, serial, time, button, state);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue