From 73a578c46e9d118cd65e77eee6abfacaa1565270 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Jan 2026 14:16:40 +0100 Subject: [PATCH 1/2] Implement window-manipulation for Linux --- Photino.Native/Photino.Linux.cpp | 70 ++++++++++++++++++++++++++++++++ Photino.Native/Photino.h | 16 ++++++++ 2 files changed, 86 insertions(+) diff --git a/Photino.Native/Photino.Linux.cpp b/Photino.Native/Photino.Linux.cpp index fff9257..79ee265 100644 --- a/Photino.Native/Photino.Linux.cpp +++ b/Photino.Native/Photino.Linux.cpp @@ -46,6 +46,7 @@ gboolean on_window_state_event(GtkWidget *widget, GdkEventWindowState *event, gp gboolean on_widget_deleted(GtkWidget *widget, GdkEvent *event, gpointer self); gboolean on_focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer self); gboolean on_focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer self); +gboolean on_button_press_event(GtkWidget *widget, GdkEvent *event, gpointer self); gboolean on_webview_context_menu(WebKitWebView *web_view, GtkWidget *default_menu, WebKitHitTestResult *hit_test_result, @@ -255,6 +256,12 @@ Photino::Photino(PhotinoInitParams *initParams) : _webview(nullptr) Photino::Show(false); + g_signal_connect(G_OBJECT(_webview), "button-press-event", + G_CALLBACK(on_button_press_event), + this); + + gtk_widget_add_events(GTK_WIDGET(_webview), GDK_BUTTON_PRESS_MASK); + g_signal_connect(G_OBJECT(_window), "focus-in-event", G_CALLBACK(on_focus_in_event), this); @@ -678,6 +685,54 @@ void Photino::SetZoom(int zoom) webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(_webview), newZoom); } +void Photino::StartDragging() +{ + if (!_lastButtonEvent.valid) + { + return; + } + + gtk_window_begin_move_drag(GTK_WINDOW(_window), _lastButtonEvent.button, + _lastButtonEvent.x_root, _lastButtonEvent.y_root, _lastButtonEvent.time); +} + +void Photino::StartResizing(PhotinoWindowHitTestCode hitTestCode) +{ + if (!_lastButtonEvent.valid) + { + return; + } + + GdkWindowEdge edge = [hitTestCode]() -> GdkWindowEdge { + switch (hitTestCode) + { + case PhotinoWindowHitTestCode::TopLeft: + return GdkWindowEdge::GDK_WINDOW_EDGE_NORTH_WEST; + case PhotinoWindowHitTestCode::Top: + return GdkWindowEdge::GDK_WINDOW_EDGE_NORTH; + case PhotinoWindowHitTestCode::TopRight: + return GdkWindowEdge::GDK_WINDOW_EDGE_NORTH_EAST; + case PhotinoWindowHitTestCode::Left: + return GdkWindowEdge::GDK_WINDOW_EDGE_WEST; + case PhotinoWindowHitTestCode::Right: + return GdkWindowEdge::GDK_WINDOW_EDGE_EAST; + case PhotinoWindowHitTestCode::BottomLeft: + return GdkWindowEdge::GDK_WINDOW_EDGE_SOUTH_WEST; + case PhotinoWindowHitTestCode::Bottom: + return GdkWindowEdge::GDK_WINDOW_EDGE_SOUTH; + case PhotinoWindowHitTestCode::BottomRight: + return GdkWindowEdge::GDK_WINDOW_EDGE_SOUTH_EAST; + default: + return GdkWindowEdge(-1); + } + }(); + if (edge != GdkWindowEdge(-1)) + { + gtk_window_begin_resize_drag(GTK_WINDOW(_window), edge, _lastButtonEvent.button, + _lastButtonEvent.x_root, _lastButtonEvent.y_root, _lastButtonEvent.time); + } +} + void Photino::SetTransparentEnabled(bool enabled) { _transparentEnabled = enabled; @@ -1038,6 +1093,21 @@ gboolean on_webview_context_menu(WebKitWebView *web_view, GtkWidget *default_men return !instance->_contextMenuEnabled; } +gboolean on_button_press_event(GtkWidget *widget, GdkEvent *event, gpointer self) +{ + Photino *instance = ((Photino *)self); + GdkEventButton *buttonEvent = ((GdkEventButton*)event); + std::exchange(instance->_lastButtonEvent, Photino::LastButtonEvent{ + .x_root = buttonEvent->x_root, + .y_root = buttonEvent->y_root, + .time = buttonEvent->time, + .button = buttonEvent->button, + .event = std::unique_ptr{gdk_event_copy(event)}, + .valid = true, + }); + return FALSE; +} + gboolean on_permission_request(WebKitWebView *web_view, WebKitPermissionRequest *request, gpointer user_data) { //GtkWidget *dialog = gtk_message_dialog_new( diff --git a/Photino.Native/Photino.h b/Photino.Native/Photino.h index ea314c9..8dc9344 100644 --- a/Photino.Native/Photino.h +++ b/Photino.Native/Photino.h @@ -24,6 +24,7 @@ typedef char *AutoString; #ifdef __linux__ #include #include +#include #endif #include @@ -245,6 +246,21 @@ class Photino int _minHeight; int _maxWidth; int _maxHeight; + + struct LastButtonEvent { + struct EventDeleter { + void operator()(GdkEvent* event) const { gdk_event_free(event); } + }; + + gdouble x_root; + gdouble y_root; + guint32 time; + guint button; + std::unique_ptr event; + bool valid{false}; + + }; + LastButtonEvent _lastButtonEvent; #elif __APPLE__ static void Register(); #endif From 30f2ffd8b67c75f1bd3567dd882caf5f2e58f776 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Fri, 30 Jan 2026 14:28:53 +0100 Subject: [PATCH 2/2] Add macOS stubs --- Photino.Native/Photino.Mac.mm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Photino.Native/Photino.Mac.mm b/Photino.Native/Photino.Mac.mm index d4a958d..c0d890e 100644 --- a/Photino.Native/Photino.Mac.mm +++ b/Photino.Native/Photino.Mac.mm @@ -762,6 +762,17 @@ [_webview setMagnification: newZoom]; } + +void Photino::StartDragging() +{ + // TODO: implement +} + +void Photino::StartResizing(PhotinoWindowHitTestCode hitTestCode) +{ + // TODO: implement +} + void EnsureInvoke(dispatch_block_t block) { if ([NSThread isMainThread])