mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
Initial version of GTK Wayland backend (#205)
* Obtaining Gtk backend and runtime and displaying it in About box. * .fixes * .csometics * Initial iteration for GTK on Wayland. Works suprisingly stable. * Disable X11Utils when Wayland backend detected. * Cosmetics * .native * First iteration of CSD. * .working * .working * Calculating additional window spaced used by CSD. * Fix max window size problem. * Fix issue with rendering. * .refactoring * Fix splash screen when SSD is enable. * Fix issue with mouse scrolling when CSD is enable. * Not ideal fix for no keyboard input in parent window. * Fix problem with XDisplay compilation and change name of GdkBackend to GtkBackend. * Introduce new WAYLAND flag. * Ctrl::GetWndScreenRect() fix for X11. * Fix to compile on mac --------- Co-authored-by: Zbigniew Rębacz <zbigniew.rebacz@hotmail.com>
This commit is contained in:
parent
8077bb9c86
commit
511ff1e991
18 changed files with 391 additions and 77 deletions
|
|
@ -38,6 +38,9 @@
|
|||
#ifndef flagGTK
|
||||
#define flagGTK
|
||||
#endif
|
||||
#ifdef flagWAYLAND
|
||||
#define GUI_GTK_WAYLAND
|
||||
#endif
|
||||
#define GUIPLATFORM_INCLUDE "Gtk.h"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -91,8 +91,10 @@ file
|
|||
GtkDrawOp.cpp,
|
||||
GtkDrawText.cpp,
|
||||
GtkDrawImage.cpp,
|
||||
GdkBackend.cpp,
|
||||
GdkImage.cpp,
|
||||
GtkUtil.cpp,
|
||||
GtkCSD.cpp,
|
||||
GtkX11Util.cpp,
|
||||
GtkCtrl.h,
|
||||
GtkCtrl.cpp,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ static void sCheckGuiLock()
|
|||
void Ctrl::RefreshFrame(const Rect& r) {
|
||||
sCheckGuiLock();
|
||||
GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
|
||||
if(!IsOpen() || !IsVisible() || r.IsEmpty()) return;
|
||||
if(!IsOpen() || !IsVisible() || r.IsEmpty())
|
||||
return;
|
||||
LTIMING("RefreshFrame");
|
||||
LLOG("RefreshRect " << Name() << ' ' << r);
|
||||
if(GuiPlatformRefreshFrameSpecial(r))
|
||||
|
|
|
|||
67
uppsrc/CtrlCore/GdkBackend.cpp
Normal file
67
uppsrc/CtrlCore/GdkBackend.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include "CtrlCore.h"
|
||||
|
||||
#ifdef GUI_GTK
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
namespace Upp {
|
||||
namespace GdkBackend {
|
||||
|
||||
Type Get()
|
||||
{
|
||||
static auto backend = Type::UNKNOWN;
|
||||
if (backend != Type::UNKNOWN) {
|
||||
return backend;
|
||||
}
|
||||
|
||||
auto* display = gdk_display_get_default();
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_DISPLAY(display)) {
|
||||
backend = Type::X11;
|
||||
return backend;
|
||||
}
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY(display)) {
|
||||
backend = Type::WAYLAND;
|
||||
return backend;
|
||||
}
|
||||
#endif
|
||||
return backend;
|
||||
}
|
||||
|
||||
bool IsWayland()
|
||||
{
|
||||
return Get() == Type::WAYLAND;
|
||||
}
|
||||
|
||||
bool IsX11()
|
||||
{
|
||||
return Get() == Type::X11;
|
||||
}
|
||||
|
||||
bool IsRunningOnWayland()
|
||||
{
|
||||
static bool running = GetEnv("XDG_SESSION_TYPE") == "wayland";
|
||||
return running;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String ToString(GdkBackend::Type t)
|
||||
{
|
||||
switch (t) {
|
||||
case GdkBackend::Type::X11: return "X11";
|
||||
case GdkBackend::Type::WAYLAND: return "Wayland";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -164,11 +164,51 @@ public:
|
|||
~ImageGdk();
|
||||
};
|
||||
|
||||
class GtkCSD final {
|
||||
public:
|
||||
static bool IsSSDSupported();
|
||||
|
||||
public:
|
||||
GtkCSD(GdkWindowTypeHint hint);
|
||||
|
||||
bool IsEnable() const { return enable; }
|
||||
|
||||
int ExtraWidth() const { return left_margin + right_margin; }
|
||||
int ExtraHeight() const { return top_margin + bottom_margin; }
|
||||
|
||||
int LeftMaring() const { return left_margin; }
|
||||
int RightMargin() const { return right_margin; }
|
||||
int TopMargin() const { return top_margin; }
|
||||
int BottomMargin() const { return bottom_margin; }
|
||||
|
||||
private:
|
||||
void FindMargins(GdkWindowTypeHint hint);
|
||||
|
||||
private:
|
||||
int left_margin = 0, right_margin = 0, top_margin = 0, bottom_margin = 0;
|
||||
bool enable = false;
|
||||
};
|
||||
|
||||
namespace GdkBackend {
|
||||
|
||||
enum class Type {
|
||||
X11,
|
||||
WAYLAND,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
Type Get();
|
||||
bool IsX11();
|
||||
bool IsWayland();
|
||||
|
||||
bool IsRunningOnWayland();
|
||||
}
|
||||
|
||||
String ToString(GdkBackend::Type b);
|
||||
|
||||
String FilesClipFromUrisFree(gchar **uris);
|
||||
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf);
|
||||
|
||||
bool RunningOnWayland();
|
||||
|
||||
GdkAtom GAtom(const String& id);
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
|
|
@ -183,9 +223,12 @@ Vector<int> GetPropertyInts(GdkWindow *w, const char *property);
|
|||
|
||||
#define GUIPLATFORM_CTRL_TOP_DECLS \
|
||||
GtkWidget *window; \
|
||||
GtkIMContext *im_context; \
|
||||
GtkWidget *header = nullptr; \
|
||||
GtkWidget *drawing_area = nullptr; \
|
||||
GtkIMContext *im_context = nullptr; \
|
||||
GtkIMContext *im_context_simple; \
|
||||
GtkIMContext *im_context_multi; \
|
||||
One<GtkCSD> csd; \
|
||||
int64 cursor_id; \
|
||||
int id; \
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public:
|
|||
|
||||
class DHCtrl : Ctrl {};
|
||||
|
||||
void InitGtkApp(int argc, char **argv, const char **envptr);
|
||||
bool InitGtkApp(int argc, char **argv, const char **envptr);
|
||||
void ExitGtkApp();
|
||||
|
||||
#define GUI_APP_MAIN \
|
||||
|
|
@ -18,7 +18,8 @@ void GuiMainFn_(); \
|
|||
int main(int argc, char **argv, const char **envptr) { \
|
||||
UPP::AppInit__(argc, (const char **)argv, envptr); \
|
||||
GUI_APP_MAIN_HOOK \
|
||||
UPP::InitGtkApp(argc, argv, envptr); \
|
||||
if (!UPP::InitGtkApp(argc, argv, envptr)) \
|
||||
return -1; \
|
||||
UPP::AppExecute__(GuiMainFn_); \
|
||||
UPP::Ctrl::CloseTopCtrls(); \
|
||||
UPP::ExitGtkApp(); \
|
||||
|
|
|
|||
|
|
@ -66,21 +66,27 @@ void Ctrl::ThemeChanged(void *)
|
|||
PostReSkin();
|
||||
}
|
||||
|
||||
void InitGtkApp(int argc, char **argv, const char **envptr)
|
||||
bool InitGtkApp(int argc, char **argv, const char **envptr)
|
||||
{
|
||||
LLOG(rmsecs() << " InitGtkApp");
|
||||
|
||||
XInitThreads(); // otherwise there are errors despide GuiLock
|
||||
|
||||
running_on_wayland = GetEnv("XDG_SESSION_TYPE") == "wayland";
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 10, 0)
|
||||
gdk_set_allowed_backends("x11"); // this fixes some wayland issues
|
||||
String backends = "x11,wayland";
|
||||
#ifdef GUI_GTK_WAYLAND
|
||||
backends = "wayland,x11";
|
||||
#endif
|
||||
gdk_set_allowed_backends(backends);
|
||||
#endif
|
||||
|
||||
if (!gtk_init_check(&argc, &argv)) {
|
||||
Cerr() << t_("Failed to initialized GTK app!") << "\n";
|
||||
return false;
|
||||
}
|
||||
if (GdkBackend::IsX11()) {
|
||||
XInitThreads(); // otherwise there are errors despide GuiLock
|
||||
}
|
||||
EnterGuiMutex();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
|
||||
Ctrl::SetUHDEnabled(true);
|
||||
|
||||
Ctrl::scale = 1;
|
||||
|
|
@ -92,15 +98,19 @@ void InitGtkApp(int argc, char **argv, const char **envptr)
|
|||
Ctrl::ReSkin();
|
||||
g_timeout_add(20, (GSourceFunc) Ctrl::TimeHandler, NULL);
|
||||
InstallPanicMessageBox(Ctrl::PanicMsgBox);
|
||||
gdk_window_add_filter(NULL, Ctrl::RootKeyFilter, NULL);
|
||||
if (GdkBackend::IsX11())
|
||||
gdk_window_add_filter(NULL, Ctrl::RootKeyFilter, NULL);
|
||||
#if CATCH_ERRORS
|
||||
g_log_set_default_handler (CatchError, 0);
|
||||
#endif
|
||||
GtkSettings *settings = gtk_settings_get_default ();
|
||||
|
||||
GtkSettings *settings = gtk_settings_get_default();
|
||||
if(settings) {
|
||||
g_signal_connect_swapped(settings, "notify::gtk-theme-name", G_CALLBACK(Ctrl::ThemeChanged), NULL);
|
||||
g_signal_connect_swapped(settings, "notify::gtk-application-prefer-dark-theme", G_CALLBACK(Ctrl::ThemeChanged), NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExitGtkApp()
|
||||
|
|
|
|||
82
uppsrc/CtrlCore/GtkCSD.cpp
Normal file
82
uppsrc/CtrlCore/GtkCSD.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#include <CtrlCore/CtrlCore.h>
|
||||
|
||||
#ifdef GUI_GTK
|
||||
|
||||
namespace Upp {
|
||||
|
||||
bool GtkCSD::IsSSDSupported()
|
||||
{
|
||||
if (GdkBackend::IsX11()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Rewrite to negotiate with window manager once XDG decoration protocol will be
|
||||
// stable. (https://wayland.app/protocols/xdg-decoration-unstable-v1)
|
||||
|
||||
// NOTE: Server side decoration are optional. It might be supported by Window manager or
|
||||
// not. Let's have a list of desktop environments on which we tested it works correctly.
|
||||
auto desktop = GetEnv("XDG_SESSION_DESKTOP");
|
||||
if (desktop == "KDE") {
|
||||
return true;
|
||||
//return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GtkCSD::GtkCSD(GdkWindowTypeHint hint)
|
||||
{
|
||||
if (!GdkBackend::IsWayland())
|
||||
return;
|
||||
if (IsSSDSupported()) {
|
||||
if (hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) {
|
||||
FindMargins(hint);
|
||||
enable = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (hint == GDK_WINDOW_TYPE_HINT_COMBO) {
|
||||
return;
|
||||
}
|
||||
|
||||
FindMargins(hint);
|
||||
enable = true;
|
||||
}
|
||||
|
||||
void GtkCSD::FindMargins(GdkWindowTypeHint hint)
|
||||
{
|
||||
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
GtkWidget* header;
|
||||
if (findarg(hint, GDK_WINDOW_TYPE_HINT_POPUP_MENU) >= 0) {
|
||||
header = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(header, 1, 1);
|
||||
gtk_window_set_titlebar((GtkWindow *)win, header);
|
||||
} else {
|
||||
header = gtk_header_bar_new();
|
||||
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header), TRUE);
|
||||
gtk_window_set_titlebar((GtkWindow *)win, header);
|
||||
}
|
||||
GtkWidget* drawing_area = gtk_drawing_area_new();
|
||||
gtk_container_add(GTK_CONTAINER(win), drawing_area);
|
||||
gtk_widget_show_all(win);
|
||||
|
||||
gdk_window_get_origin(gtk_widget_get_window(drawing_area), &left_margin, &top_margin);
|
||||
|
||||
gint drawing_area_width = gtk_widget_get_allocated_width(drawing_area);
|
||||
gint drawing_area_height = gtk_widget_get_allocated_height(drawing_area);
|
||||
|
||||
gint win_width = gtk_widget_get_allocated_width(win);
|
||||
gint win_height = gtk_widget_get_allocated_height(win);
|
||||
|
||||
right_margin = win_width - left_margin - drawing_area_width;
|
||||
bottom_margin = win_height - top_margin - drawing_area_height;
|
||||
|
||||
gtk_widget_destroy(drawing_area);
|
||||
gtk_widget_destroy(header);
|
||||
gtk_widget_destroy(win);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -30,22 +30,42 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
|||
w.gdk = nullptr;
|
||||
|
||||
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||
GdkWindowTypeHint type_hint;
|
||||
if(popup && !owner) {
|
||||
gtk_window_set_decorated(gtk(), FALSE);
|
||||
// gtk_window_set_has_frame(gtk(), FALSE);
|
||||
gtk_window_set_type_hint(gtk(), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
|
||||
type_hint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
|
||||
}
|
||||
else
|
||||
gtk_window_set_type_hint(gtk(), popup ? GDK_WINDOW_TYPE_HINT_COMBO
|
||||
: tw && tw->tool ? GDK_WINDOW_TYPE_HINT_UTILITY
|
||||
: owner ? GDK_WINDOW_TYPE_HINT_DIALOG
|
||||
: GDK_WINDOW_TYPE_HINT_NORMAL);
|
||||
|
||||
else {
|
||||
type_hint = popup ? GDK_WINDOW_TYPE_HINT_COMBO
|
||||
: tw && tw->tool ? GDK_WINDOW_TYPE_HINT_UTILITY
|
||||
: owner ? GDK_WINDOW_TYPE_HINT_DIALOG
|
||||
: GDK_WINDOW_TYPE_HINT_NORMAL;
|
||||
}
|
||||
gtk_window_set_type_hint(gtk(), type_hint);
|
||||
|
||||
top->csd.Create(type_hint);
|
||||
if (top->csd->IsEnable()) {
|
||||
if (findarg(type_hint, GDK_WINDOW_TYPE_HINT_POPUP_MENU) >= 0) {
|
||||
top->header = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(top->header, 1, 1);
|
||||
gtk_window_set_titlebar(gtk(), top->header);
|
||||
} else {
|
||||
top->header = gtk_header_bar_new();
|
||||
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(top->header), TRUE);
|
||||
gtk_window_set_titlebar(gtk(), top->header);
|
||||
}
|
||||
|
||||
top->drawing_area = gtk_drawing_area_new();
|
||||
gtk_widget_set_can_focus(top->drawing_area, TRUE);
|
||||
} else {
|
||||
top->drawing_area = top->window;
|
||||
}
|
||||
|
||||
top->cursor_id = -1;
|
||||
|
||||
gtk_widget_set_events(top->window, GDK_ALL_EVENTS_MASK & ~GDK_POINTER_MOTION_HINT_MASK);
|
||||
g_signal_connect(top->window, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
||||
g_signal_connect(top->window, "draw", G_CALLBACK(GtkDraw), (gpointer)(uintptr_t)top->id);
|
||||
gtk_widget_set_events(top->drawing_area, GDK_ALL_EVENTS_MASK & ~GDK_POINTER_MOTION_HINT_MASK & ~GDK_SMOOTH_SCROLL_MASK);
|
||||
g_signal_connect(top->drawing_area, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
||||
g_signal_connect(top->drawing_area, "draw", G_CALLBACK(GtkDraw), (gpointer)(uintptr_t)top->id);
|
||||
|
||||
GdkWindowTypeHint hint = gtk_window_get_type_hint(gtk());
|
||||
if(tw && findarg(hint, GDK_WINDOW_TYPE_HINT_NORMAL, GDK_WINDOW_TYPE_HINT_DIALOG, GDK_WINDOW_TYPE_HINT_UTILITY) >= 0)
|
||||
|
|
@ -53,15 +73,20 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
|||
|
||||
Rect r = GetRect();
|
||||
|
||||
gtk_window_set_default_size (gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
|
||||
|
||||
// TODO: Normalize
|
||||
gtk_window_set_default_size(gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
|
||||
gtk_window_move(gtk(), LSC(r.left), LSC(r.top));
|
||||
gtk_window_resize(gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
|
||||
|
||||
if (top->header) {
|
||||
gtk_container_add(GTK_CONTAINER(top->window), top->drawing_area);
|
||||
gtk_widget_show_all(top->window);
|
||||
} else {
|
||||
gtk_widget_realize(top->window);
|
||||
}
|
||||
|
||||
gtk_widget_realize(top->window);
|
||||
|
||||
w.gdk = gtk_widget_get_window(top->window);
|
||||
|
||||
|
||||
if(owner && owner->top)
|
||||
gtk_window_set_transient_for(gtk(), owner->gtk());
|
||||
gtk_widget_set_app_paintable(top->window, TRUE);
|
||||
|
|
@ -114,8 +139,10 @@ void Ctrl::WndDestroy()
|
|||
activeCtrl = owner;
|
||||
}
|
||||
Top *top = GetTop();
|
||||
if(top->im_context)
|
||||
if(top->im_context) {
|
||||
g_object_unref(top->im_context);
|
||||
top->im_context = nullptr;
|
||||
}
|
||||
gtk_widget_destroy(top->window);
|
||||
isopen = false;
|
||||
popup = false;
|
||||
|
|
@ -124,8 +151,14 @@ void Ctrl::WndDestroy()
|
|||
int q = FindCtrl(this);
|
||||
if(q >= 0)
|
||||
wins.Remove(q);
|
||||
if(owner)
|
||||
if(owner) {
|
||||
if(owner->utop->csd->IsEnable()) {
|
||||
// TODO: This fix the problem with keyboard when backing to original window, but
|
||||
// the previous control is not being focused like it should be.
|
||||
gtk_window_set_focus(owner->gtk(), owner->utop->drawing_area);
|
||||
}
|
||||
owner->WndUpdate();
|
||||
}
|
||||
TopWindow *w = dynamic_cast<TopWindow *>(this);
|
||||
if(w && w->overlapped.GetWidth() && w->overlapped.GetHeight())
|
||||
SetRect(w->overlapped);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#ifdef GUI_GTK
|
||||
|
||||
#ifndef PLATFORM_OPENBSD
|
||||
#undef CurrentTime
|
||||
#endif
|
||||
|
||||
#define LLOG(x) // DLOG(x)
|
||||
|
||||
namespace Upp {
|
||||
|
|
@ -76,8 +80,6 @@ GtkWindow *Ctrl::gtk() const
|
|||
return top ? (GtkWindow *)top->window : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ _DBG_
|
|||
guint time, gpointer user_data, bool paste);
|
||||
static bool ProcessInvalids();
|
||||
|
||||
friend void InitGtkApp(int argc, char **argv, const char **envptr);
|
||||
friend bool InitGtkApp(int argc, char **argv, const char **envptr);
|
||||
friend void GuiPlatformGripResize(TopWindow *q);
|
||||
|
||||
public: // really private:
|
||||
|
|
@ -187,7 +187,7 @@ public: // really private:
|
|||
static Gclipboard& gclipboard();
|
||||
static Gclipboard& gselection();
|
||||
static String RenderPrimarySelection(const Value& fmt);
|
||||
|
||||
|
||||
static Vector<Event<>> hotkey;
|
||||
static Vector<dword> keyhot;
|
||||
static Vector<dword> modhot;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#ifdef GUI_GTK
|
||||
|
||||
#ifndef PLATFORM_OPENBSD
|
||||
#undef CurrentTime
|
||||
#endif
|
||||
|
||||
namespace Upp {
|
||||
|
||||
#define LLOG(x) // DLOG(x)
|
||||
|
|
@ -89,6 +93,7 @@ gboolean Ctrl::GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
|||
|
||||
SystemDraw w(cr);
|
||||
painting = true;
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
|
||||
Rect r = RectC((int)x1, (int)y1, (int)ceil(x2 - x1), (int)ceil(y2 - y1));
|
||||
|
|
@ -136,7 +141,7 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
|||
p->CancelPreedit();
|
||||
if(p) {
|
||||
Top *top = p->GetTop();
|
||||
if(top) {
|
||||
if(top && top->im_context) {
|
||||
if(((GdkEventFocus *)event)->in)
|
||||
gtk_im_context_focus_in(top->im_context);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Rect Ctrl::GetFrameMargins()
|
|||
return frameMargins != Rect(0, 0, 0, 0) ? frameMargins : Rect(8, 32, 8, 8);
|
||||
}
|
||||
|
||||
void TopWindow::SyncSizeHints()
|
||||
void TopWindow::SyncSizeHints()
|
||||
{
|
||||
GuiLock __;
|
||||
if(!top)
|
||||
|
|
@ -25,13 +25,13 @@ void TopWindow::SyncSizeHints()
|
|||
Size sz = sz0;
|
||||
if(sizeable)
|
||||
sz = GetMinSize();
|
||||
m.min_width = LSC(sz.cx);
|
||||
m.min_height = LSC(sz.cy);
|
||||
m.min_width = LSC(sz.cx + utop->csd->ExtraWidth());
|
||||
m.min_height = LSC(sz.cy + utop->csd->ExtraHeight());
|
||||
sz = sz0;
|
||||
if(sizeable)
|
||||
sz = GetMaxSize();
|
||||
m.max_width = LSC(sz.cx);
|
||||
m.max_height = LSC(sz.cy);
|
||||
m.max_width = LSC(sz.cx + utop->csd->ExtraWidth());
|
||||
m.max_height = LSC(sz.cy + utop->csd->ExtraHeight());
|
||||
gtk_window_set_resizable(gtk(), sizeable);
|
||||
Top *top = GetTop();
|
||||
if(top) {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void Ctrl::SetMouseCursor(const Image& image)
|
|||
if(c && topctrl->IsOpen()) {
|
||||
gdk_window_set_cursor(topctrl->gdk(), c);
|
||||
g_object_unref(c);
|
||||
if(RunningOnWayland()) // wayland is broken, need some paint to change the cursor...
|
||||
if(GdkBackend::IsX11() && GdkBackend::IsRunningOnWayland()) // wayland is broken, need some paint to change the cursor...
|
||||
topctrl->Refresh(0, 0, 1, 1);
|
||||
gdk_display_flush(gdk_display_get_default()); // Make it visible immediately
|
||||
}
|
||||
|
|
@ -153,14 +153,28 @@ void Ctrl::UnregisterSystemHotKey(int id)
|
|||
Rect Ctrl::GetWndScreenRect() const
|
||||
{
|
||||
GuiLock __;
|
||||
if(IsOpen()) {
|
||||
gint x, y;
|
||||
gdk_window_get_position(gdk(), &x, &y);
|
||||
gint width = gdk_window_get_width(gdk());
|
||||
gint height = gdk_window_get_height(gdk());
|
||||
return SCL(x, y, width, height);
|
||||
if(!IsOpen()) {
|
||||
return Null;
|
||||
}
|
||||
return Null;
|
||||
|
||||
gint x, y;
|
||||
gint width, height;
|
||||
|
||||
if (GdkBackend::IsWayland()) {
|
||||
if(top && utop->csd->IsEnable()) {
|
||||
gdk_window_get_origin(gtk_widget_get_window(utop->drawing_area), &x, &y);
|
||||
width = gtk_widget_get_allocated_width(utop->drawing_area);
|
||||
height = gtk_widget_get_allocated_height(utop->drawing_area);
|
||||
} else {
|
||||
gdk_window_get_geometry(gdk(), &x, &y, &width, &height);
|
||||
}
|
||||
} else {
|
||||
gdk_window_get_position(gdk(), &x, &y);
|
||||
width = gdk_window_get_width(gdk());
|
||||
height = gdk_window_get_height(gdk());
|
||||
}
|
||||
|
||||
return SCL(x, y, width, height);
|
||||
}
|
||||
|
||||
void Ctrl::WndShow(bool b)
|
||||
|
|
@ -169,7 +183,6 @@ void Ctrl::WndShow(bool b)
|
|||
LLOG("WndShow " << Name() << ", " << b);
|
||||
Top *top = GetTop();
|
||||
if(IsOpen() && top) {
|
||||
|
||||
if(b)
|
||||
gtk_widget_show_now(top->window);
|
||||
else
|
||||
|
|
@ -197,20 +210,24 @@ Rect Ctrl::GetWorkArea() const
|
|||
void Ctrl::GetWorkArea(Array<Rect>& rc)
|
||||
{
|
||||
GuiLock __;
|
||||
rc.Clear();
|
||||
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||
GdkDisplay *s = gdk_display_get_default();
|
||||
int n = gdk_display_get_n_monitors(s);
|
||||
rc.Clear();
|
||||
Vector<int> netwa;
|
||||
for(int i = 0; i < n; i++) {
|
||||
GdkRectangle rr;
|
||||
gdk_monitor_get_workarea(gdk_display_get_monitor(s, i), &rr);
|
||||
auto *pMonitor = gdk_display_get_monitor(s, i);
|
||||
if (GdkBackend::IsWayland()) {
|
||||
gdk_monitor_get_geometry(pMonitor, &rr);
|
||||
} else {
|
||||
gdk_monitor_get_workarea(pMonitor, &rr);
|
||||
}
|
||||
rc.Add(SCL(rr.x, rr.y, rr.width, rr.height));
|
||||
}
|
||||
#else
|
||||
GdkScreen *s = gdk_screen_get_default();
|
||||
int n = gdk_screen_get_n_monitors(s);
|
||||
rc.Clear();
|
||||
Vector<int> netwa;
|
||||
for(int i = 0; i < n; i++) {
|
||||
GdkRectangle rr;
|
||||
|
|
@ -236,19 +253,45 @@ Rect Ctrl::GetVirtualWorkArea()
|
|||
Rect Ctrl::GetVirtualScreenArea()
|
||||
{
|
||||
GuiLock __;
|
||||
auto pRootWindow = gdk_screen_get_root_window(gdk_screen_get_default());
|
||||
if (!pRootWindow) {
|
||||
ASSERT("Failed to obtain root window!");
|
||||
return Rect();
|
||||
}
|
||||
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||
if (GdkBackend::IsWayland()) {
|
||||
GdkRectangle rr;
|
||||
auto *pDisplay = gdk_display_get_default();
|
||||
auto *pMonitor = gdk_display_get_monitor_at_window(pDisplay, pRootWindow);
|
||||
if (!pMonitor) {
|
||||
ASSERT("Failed to obtain monitor!");
|
||||
return Rect();
|
||||
}
|
||||
gdk_monitor_get_geometry(pMonitor, &rr);
|
||||
return SCL(rr.x, rr.y, rr.width, rr.height);
|
||||
}
|
||||
#endif
|
||||
if (GdkBackend::IsWayland()) {
|
||||
ASSERT("GTK Wayland backend not supported before 3.22 GTK version.");
|
||||
return Rect();
|
||||
}
|
||||
gint x, y, width, height;
|
||||
gdk_window_get_geometry(gdk_screen_get_root_window(gdk_screen_get_default()),
|
||||
&x, &y, &width, &height);
|
||||
Rect r = SCL(x, y, width, height);
|
||||
return r;
|
||||
gdk_window_get_geometry(pRootWindow, &x, &y, &width, &height);
|
||||
return SCL(x, y, width, height);
|
||||
}
|
||||
|
||||
Rect Ctrl::GetPrimaryWorkArea()
|
||||
{
|
||||
GuiLock __;
|
||||
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||
if (GdkBackend::IsWayland()) {
|
||||
// NOTE: WorkArea on Wayland is not available... Window manager decides where to put
|
||||
// windows.
|
||||
return GetVirtualScreenArea();
|
||||
}
|
||||
GdkRectangle rr;
|
||||
gdk_monitor_get_workarea(gdk_display_get_primary_monitor(gdk_display_get_default()), &rr);
|
||||
auto* display = gdk_display_get_default();
|
||||
gdk_monitor_get_workarea(gdk_display_get_primary_monitor(display), &rr);
|
||||
return SCL(rr.x, rr.y, rr.width, rr.height);
|
||||
#else
|
||||
static Rect r;
|
||||
|
|
@ -384,16 +427,28 @@ void WakeUpGuiThread();
|
|||
void Ctrl::WndInvalidateRect(const Rect& r)
|
||||
{
|
||||
GuiLock __;
|
||||
LLOG("WndInvalidateRect " << r);
|
||||
|
||||
Rect nr = r;
|
||||
if (top && utop->csd->IsEnable()) {
|
||||
gint x, y;
|
||||
gdk_window_get_origin(gtk_widget_get_window(utop->drawing_area), &x, &y);
|
||||
|
||||
nr.left += x;
|
||||
nr.top += y;
|
||||
|
||||
nr.right += x;
|
||||
nr.bottom += y;
|
||||
}
|
||||
|
||||
Rect rr;
|
||||
if(scale > 1) {
|
||||
rr.left = r.left / 2;
|
||||
rr.top = r.top / 2;
|
||||
rr.right = (r.right + 1) / 2;
|
||||
rr.bottom = (r.bottom + 1) / 2;
|
||||
rr.left = nr.left / 2;
|
||||
rr.top = nr.top / 2;
|
||||
rr.right = (nr.right + 1) / 2;
|
||||
rr.bottom = (nr.bottom + 1) / 2;
|
||||
}
|
||||
else
|
||||
rr = r;
|
||||
rr = nr;
|
||||
|
||||
// as gtk3 dropped thread locking, we need to push invalid rectangles onto main loop
|
||||
for(Win& win : wins) {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
#include "CtrlCore.h"
|
||||
#include <CtrlCore/CtrlCore.h>
|
||||
|
||||
#ifdef GUI_GTK
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
|
||||
namespace Upp {
|
||||
|
||||
#define Time XTime
|
||||
#define Font XFont
|
||||
#define Display XDisplay
|
||||
#define Picture XPicture
|
||||
|
||||
#ifndef PLATFORM_OPENBSD // avoid warning
|
||||
#undef CurrentTime
|
||||
#define CurrentTime XCurrentTime
|
||||
#endif
|
||||
|
||||
|
|
@ -20,13 +17,14 @@ namespace Upp {
|
|||
#undef Picture
|
||||
#undef Time
|
||||
#undef Font
|
||||
#undef Display
|
||||
|
||||
#ifndef PLATFORM_OPENBSD // avoid warning
|
||||
#undef CurrentTime
|
||||
#endif
|
||||
|
||||
XDisplay *Xdisplay()
|
||||
namespace Upp {
|
||||
|
||||
_XDisplay *Xdisplay()
|
||||
{
|
||||
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||
}
|
||||
|
|
@ -89,6 +87,9 @@ Atom XAtom(const char *name)
|
|||
|
||||
Vector<int> GetPropertyInts(GdkWindow *w, const char *property)
|
||||
{
|
||||
if (GdkBackend::IsWayland())
|
||||
return {}; // Not supported on Wayland...
|
||||
|
||||
GuiLock __;
|
||||
Vector<int> result;
|
||||
String p = GetProperty(GDK_WINDOW_XID(w), XAtom(property), AnyPropertyType);
|
||||
|
|
@ -114,6 +115,9 @@ dword X11mods(dword key)
|
|||
|
||||
int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb)
|
||||
{
|
||||
if (GdkBackend::IsWayland())
|
||||
return -1; // Not supported on Wayland...
|
||||
|
||||
GuiLock __;
|
||||
ASSERT(key >= K_DELTA);
|
||||
gdk_x11_display_error_trap_push(gdk_display_get_default());
|
||||
|
|
@ -142,6 +146,9 @@ int Ctrl::RegisterSystemHotKey(dword key, Function<void ()> cb)
|
|||
|
||||
void Ctrl::UnregisterSystemHotKey(int id)
|
||||
{
|
||||
if (GdkBackend::IsWayland())
|
||||
return; // Not supported on Wayland...
|
||||
|
||||
GuiLock __;
|
||||
if(id >= 0 && id < hotkey.GetCount() && hotkey[id]) {
|
||||
gdk_x11_display_error_trap_push(gdk_display_get_default());
|
||||
|
|
@ -158,6 +165,9 @@ void Ctrl::UnregisterSystemHotKey(int id)
|
|||
|
||||
GdkFilterReturn Ctrl::RootKeyFilter(GdkXEvent *xevent, GdkEvent *Xevent, gpointer data)
|
||||
{
|
||||
if (GdkBackend::IsWayland())
|
||||
return GDK_FILTER_CONTINUE; // Not supported on Wayland...
|
||||
|
||||
XEvent *event = (XEvent *)xevent;
|
||||
if(event->type == KeyPress)
|
||||
for(int i = 0; i < hotkey.GetCount(); i++)
|
||||
|
|
@ -172,5 +182,4 @@ GdkFilterReturn Ctrl::RootKeyFilter(GdkXEvent *xevent, GdkEvent *Xevent, gpointe
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ void Ctrl::InitX11(const char *display)
|
|||
_NET_Supported().Add(nets[i]);
|
||||
|
||||
Font::SetDefaultFont(Arial(12));
|
||||
|
||||
|
||||
ReSkin();
|
||||
|
||||
GUI_GlobalStyle_Write(GUISTYLE_XP);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ String SplashCtrl::GenerateVersionInfo(bool qtf, bool about)
|
|||
#endif
|
||||
|
||||
#ifdef GUI_GTK
|
||||
h << " Gtk";
|
||||
h << " Gtk::" << ToString(GdkBackend::Get());
|
||||
#endif
|
||||
#ifdef FLATPAK
|
||||
h << " Flatpak";
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ mainconfig
|
|||
"" = "GUI PEAKMEM",
|
||||
"" = "GUI HEAPLOG",
|
||||
"" = "GUI X11",
|
||||
"" = "GUI GTK WAYLAND",
|
||||
"" = "GUI DEBUGCODE";
|
||||
|
||||
custom() "",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue