summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--documentation/src/bundled-libs.dox4
-rw-r--r--libdecor/src/plugins/gtk/libdecor-gtk.c222
2 files changed, 224 insertions, 2 deletions
diff --git a/documentation/src/bundled-libs.dox b/documentation/src/bundled-libs.dox
index 2de0b680e..4ea3276bc 100644
--- a/documentation/src/bundled-libs.dox
+++ b/documentation/src/bundled-libs.dox
@@ -23,14 +23,14 @@ The nanosvg library is not affected.
\section bundled-status Current status
\code
-Current versions of bundled libraries (as of August 25, 2023):
+Current versions of bundled libraries (as of September 13, 2023):
Library Version/git commit Release date FLTK Version
--------------------------------------------------------------------------
jpeg jpeg-9e 2022-01-16 1.4.0
nanosvg abcd277ea4 [1] 2022-12-22 1.4.0
png libpng-1.6.40 2023-06-21 1.4.0
zlib zlib-1.3 2023-08-18 1.4.0
- libdecor ca6e6b68 [2] 2023-08-25 1.4.0
+ libdecor 422abaf9 [2] 2023-09-07 1.4.0
--------------------------------------------------------------------------
Previous versions of bundled libraries (FLTK 1.3.x):
diff --git a/libdecor/src/plugins/gtk/libdecor-gtk.c b/libdecor/src/plugins/gtk/libdecor-gtk.c
index 77e64f7cd..bc8290f14 100644
--- a/libdecor/src/plugins/gtk/libdecor-gtk.c
+++ b/libdecor/src/plugins/gtk/libdecor-gtk.c
@@ -189,6 +189,7 @@ struct seat {
struct wl_seat *wl_seat;
struct wl_pointer *wl_pointer;
+ struct wl_touch *wl_touch;
struct wl_surface *cursor_surface;
struct wl_cursor *current_cursor;
@@ -201,10 +202,12 @@ struct seat {
struct wl_cursor *cursor_left_ptr;
struct wl_surface *pointer_focus;
+ struct wl_surface *touch_focus;
int pointer_x, pointer_y;
uint32_t pointer_button_time_stamp;
+ uint32_t touch_down_time_stamp;
uint32_t serial;
@@ -277,6 +280,7 @@ struct libdecor_frame_gtk {
enum libdecor_capabilities capabilities;
struct border_component *active;
+ struct border_component *touch_active;
struct border_component *focus;
struct border_component *grab;
@@ -401,6 +405,8 @@ libdecor_plugin_gtk_destroy(struct libdecor_plugin *plugin)
if (seat->wl_pointer)
wl_pointer_destroy(seat->wl_pointer);
+ if (seat->wl_touch)
+ wl_touch_destroy(seat->wl_touch);
if (seat->cursor_surface)
wl_surface_destroy(seat->cursor_surface);
wl_seat_destroy(seat->wl_seat);
@@ -2285,6 +2291,211 @@ static struct wl_pointer_listener pointer_listener = {
};
static void
+update_touch_focus(struct seat *seat,
+ struct libdecor_frame_gtk *frame_gtk,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ /* avoid warnings after decoration has been turned off */
+ if (GTK_IS_WIDGET(frame_gtk->header) && frame_gtk->touch_active->type == HEADER) {
+ struct header_element_data new_focus = get_header_focus(
+ GTK_HEADER_BAR(frame_gtk->header),
+ wl_fixed_to_int(x), wl_fixed_to_int(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 {
+ frame_gtk->hdr_focus.type = HEADER_NONE;
+ }
+}
+
+static void
+touch_down(void *data,
+ struct wl_touch *wl_touch,
+ uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ struct seat *seat = data;
+ struct libdecor_frame_gtk *frame_gtk;
+
+ if (!surface || !own_surface(surface))
+ return;
+
+ frame_gtk = wl_surface_get_user_data(surface);
+ if (!frame_gtk)
+ return;
+
+ seat->touch_focus = surface;
+ frame_gtk->touch_active = get_component_for_surface(frame_gtk, surface);
+
+ if (!frame_gtk->touch_active)
+ return;
+
+ update_touch_focus(seat, frame_gtk, x, y);
+
+ /* update decorations */
+ draw_decoration(frame_gtk);
+ libdecor_frame_toplevel_commit(&frame_gtk->frame);
+
+ enum libdecor_resize_edge edge =
+ LIBDECOR_RESIZE_EDGE_NONE;
+ switch (frame_gtk->touch_active->type) {
+ case SHADOW:
+ edge = component_edge(frame_gtk->touch_active,
+ wl_fixed_to_int(x),
+ wl_fixed_to_int(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->touch_down_time_stamp <
+ (uint32_t)frame_gtk->plugin_gtk->double_click_time_ms) {
+ toggle_maximized(&frame_gtk->frame);
+ }
+ else if (moveable(frame_gtk)) {
+ seat->touch_down_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);
+ }
+}
+
+static void
+touch_up(void *data,
+ struct wl_touch *wl_touch,
+ uint32_t serial,
+ uint32_t time,
+ int32_t id)
+{
+ struct seat *seat = data;
+ struct libdecor_frame_gtk *frame_gtk;
+
+ if (!seat->touch_focus || !own_surface(seat->touch_focus))
+ return;
+
+ frame_gtk = wl_surface_get_user_data(seat->touch_focus);
+ if (!frame_gtk)
+ return;
+
+ if (!frame_gtk->touch_active)
+ return;
+
+ switch (frame_gtk->touch_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->touch_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;
+ }
+
+ seat->touch_focus = NULL;
+ frame_gtk->touch_active = NULL;
+ frame_gtk->hdr_focus.widget = NULL;
+ frame_gtk->hdr_focus.type = HEADER_NONE;
+ draw_decoration(frame_gtk);
+ libdecor_frame_toplevel_commit(&frame_gtk->frame);
+}
+
+static void
+touch_motion(void *data,
+ struct wl_touch *wl_touch,
+ uint32_t time,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ struct seat *seat = data;
+ struct libdecor_frame_gtk *frame_gtk;
+
+ if (!seat->touch_focus || !own_surface(seat->touch_focus))
+ return;
+
+ frame_gtk = wl_surface_get_user_data(seat->touch_focus);
+ if (!frame_gtk)
+ return;
+
+ update_touch_focus(seat, frame_gtk, x, y);
+}
+
+static void
+touch_frame(void *data,
+ struct wl_touch *wl_touch)
+{
+}
+
+static void
+touch_cancel(void *data,
+ struct wl_touch *wl_touch)
+{
+}
+
+static struct wl_touch_listener touch_listener = {
+ touch_down,
+ touch_up,
+ touch_motion,
+ touch_frame,
+ touch_cancel
+};
+
+static void
seat_capabilities(void *data,
struct wl_seat *wl_seat,
uint32_t capabilities)
@@ -2301,6 +2512,17 @@ seat_capabilities(void *data,
wl_pointer_release(seat->wl_pointer);
seat->wl_pointer = NULL;
}
+
+ if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) &&
+ !seat->wl_touch) {
+ seat->wl_touch = wl_seat_get_touch(wl_seat);
+ wl_touch_add_listener(seat->wl_touch,
+ &touch_listener, seat);
+ } else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) &&
+ seat->wl_touch) {
+ wl_touch_release(seat->wl_touch);
+ seat->wl_touch = NULL;
+ }
}
static void