Enhancement: Fixes #288, dpa - support creating desktop windows properly

This commit is contained in:
Rory Fewell
2024-04-10 20:45:29 +01:00
parent c5ecf80bba
commit 0b4ead9921
13 changed files with 409 additions and 179 deletions

View File

@@ -31,6 +31,8 @@ add_library(
libwintc-shelldpa
src/api.c
public/api.h
src/deskwnd.c
public/deskwnd.h
src/impl-wayland.c
src/impl-wayland.h
src/impl-wndmgmt-wnck.c
@@ -39,6 +41,8 @@ add_library(
src/impl-wndmgmt-xfw.h
src/impl-x11.c
src/impl-x11.h
src/dll/layersh.c
src/dll/layersh.h
src/dll/wnck.c
src/dll/wnck.h
src/dll/xfw.c

View File

@@ -103,17 +103,6 @@ extern void (*wintc_anchor_taskband_to_bottom) (
GtkWindow* taskband
);
/**
* Assigns properties for the window to become the desktop.
*
* @param window The window.
*
* @remarks This function will be retired with a better, general purpose API.
*/
extern void (*wintc_become_desktop_window) (
GtkWindow* window
);
/**
* Retrieves the active window on the specified screen.
*

View File

@@ -0,0 +1,31 @@
#ifndef __SHELLDPA_DESKWND_H__
#define __SHELLDPA_DESKWND_H__
#include <glib.h>
#include <gtk/gtk.h>
//
// GTK OOP BOILERPLATE
//
typedef struct _WinTCDpaDesktopWindowClass
{
GtkApplicationWindowClass __parent__;
} WinTCDpaDesktopWindowClass;
typedef struct _WinTCDpaDesktopWindow
{
GtkApplicationWindow __parent__;
GdkMonitor* monitor;
} WinTCDpaDesktopWindow;
#define WINTC_TYPE_DPA_DESKTOP_WINDOW (wintc_dpa_desktop_window_get_type())
#define WINTC_DPA_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW, WinTCDpaDesktopWindow))
#define WINTC_DPA_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DPA_DESKTOP_WINDOW, WinTCDpaDesktopWindow))
#define IS_WINTC_DPA_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW))
#define IS_WINTC_DPA_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DPA_DESKTOP_WINDOW))
#define WINTC_DPA_DESKTOP_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW))
GType wintc_dpa_desktop_window_get_type(void) G_GNUC_CONST;
#endif

View File

@@ -2,5 +2,6 @@
#define __WINTC_SHELLDPA_H__
#include "@LIB_HEADER_DIR@/api.h"
#include "@LIB_HEADER_DIR@/deskwnd.h"
#endif

View File

@@ -25,10 +25,6 @@ void (*wintc_anchor_taskband_to_bottom) (
GtkWindow* taskband
) = NULL;
void (*wintc_become_desktop_window) (
GtkWindow* window
) = NULL;
WinTCWndMgmtWindow* (*wintc_wndmgmt_screen_get_active_window) (
WinTCWndMgmtScreen* screen
) = NULL;

View File

@@ -0,0 +1,177 @@
#include <glib.h>
#include <gtk/gtk.h>
#include <wintc/comgtk.h>
#include "../public/api.h"
#include "../public/deskwnd.h"
#include "dll/layersh.h"
//
// PRIVATE ENUMS
//
enum
{
PROP_MONITOR = 1
};
//
// FORWARD DECLARATIONS
//
static void wintc_dpa_desktop_window_constructed(
GObject* object
);
static void wintc_dpa_desktop_window_get_property(
GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec
);
static void wintc_dpa_desktop_window_set_property(
GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec
);
static void window_setup_wayland(
WinTCDpaDesktopWindow* wnd
);
static void window_setup_x11(
WinTCDpaDesktopWindow* wnd
);
//
// GTK TYPE DEFINITION & CTORS
//
G_DEFINE_TYPE(
WinTCDpaDesktopWindow,
wintc_dpa_desktop_window,
GTK_TYPE_APPLICATION_WINDOW
)
static void wintc_dpa_desktop_window_class_init(
WinTCDpaDesktopWindowClass* klass
)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->constructed = wintc_dpa_desktop_window_constructed;
object_class->get_property = wintc_dpa_desktop_window_get_property;
object_class->set_property = wintc_dpa_desktop_window_set_property;
g_object_class_install_property(
object_class,
PROP_MONITOR,
g_param_spec_object(
"monitor",
"Monitor",
"The monitor to map to.",
GDK_TYPE_MONITOR,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
)
);
}
static void wintc_dpa_desktop_window_init(
WINTC_UNUSED(WinTCDpaDesktopWindow* self)
) {}
//
// CLASS VIRTUAL METHODS
//
static void wintc_dpa_desktop_window_constructed(
GObject* object
)
{
WinTCDpaDesktopWindow* wnd = WINTC_DPA_DESKTOP_WINDOW(object);
if (wintc_get_display_protocol_in_use() == WINTC_DISPPROTO_WAYLAND)
{
window_setup_wayland(wnd);
}
else
{
window_setup_x11(wnd);
}
}
static void wintc_dpa_desktop_window_get_property(
GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec
)
{
WinTCDpaDesktopWindow* wnd = WINTC_DPA_DESKTOP_WINDOW(object);
switch (prop_id)
{
case PROP_MONITOR:
g_value_set_object(value, wnd->monitor);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void wintc_dpa_desktop_window_set_property(
GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec
)
{
WinTCDpaDesktopWindow* wnd = WINTC_DPA_DESKTOP_WINDOW(object);
switch (prop_id)
{
case PROP_MONITOR:
wnd->monitor = g_value_get_object(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
//
// PRIVATE FUNCTIONS
//
static void window_setup_wayland(
WinTCDpaDesktopWindow* wnd
)
{
GtkWindow* window = GTK_WINDOW(wnd);
p_gtk_layer_init_for_window(window);
p_gtk_layer_set_layer(window, GTK_LAYER_SHELL_LAYER_BACKGROUND);
p_gtk_layer_set_monitor(window, wnd->monitor);
for (int edge = 0; edge <= GTK_LAYER_SHELL_EDGE_BOTTOM; edge++)
{
p_gtk_layer_set_anchor(window, edge, TRUE);
p_gtk_layer_set_margin(window, edge, 0);
}
p_gtk_layer_set_namespace(window, "desktop");
}
static void window_setup_x11(
WinTCDpaDesktopWindow* wnd
)
{
GdkRectangle geometry;
gdk_monitor_get_geometry(wnd->monitor, &geometry);
gtk_window_move(GTK_WINDOW(wnd), geometry.x, geometry.y);
gtk_window_set_type_hint(GTK_WINDOW(wnd), GDK_WINDOW_TYPE_HINT_DESKTOP);
gtk_widget_set_size_request(
GTK_WIDGET(wnd),
geometry.width,
geometry.height
);
}

View File

@@ -0,0 +1,104 @@
#include <dlfcn.h>
#include <glib.h>
#include <wintc/comgtk.h>
#include "layersh.h"
//
// STATIC DATA
//
static gboolean s_initialized = FALSE;
//
// RESOLVED FUNCS
//
void (*p_gtk_layer_auto_exclusive_zone_enable) (
GtkWindow* window
) = NULL;
void (*p_gtk_layer_init_for_window) (
GtkWindow* window
) = NULL;
void (*p_gtk_layer_set_anchor) (
GtkWindow* window,
GtkLayerShellEdge edge,
gboolean anchor_to_edge
) = NULL;
void (*p_gtk_layer_set_layer) (
GtkWindow* window,
GtkLayerShellLayer layer
) = NULL;
void (*p_gtk_layer_set_margin) (
GtkWindow* window,
GtkLayerShellEdge edge,
int margin_size
) = NULL;
void (*p_gtk_layer_set_monitor) (
GtkWindow* window,
GdkMonitor* monitor
) = NULL;
void (*p_gtk_layer_set_namespace) (
GtkWindow* window,
const gchar* name_space
) = NULL;
//
// PUBLIC FUNCTIONS
//
gboolean init_dll_layersh()
{
void* dl_layersh = NULL;
if (s_initialized)
{
return TRUE;
}
dl_layersh = dlopen("libgtk-layer-shell.so", RTLD_LAZY | RTLD_LOCAL);
if (dl_layersh == NULL)
{
g_critical("%s", "Failed to open libgtk-layer-shell for symbols.");
return FALSE;
}
// Resolve the funcs we're using
//
p_gtk_layer_auto_exclusive_zone_enable =
dlsym(dl_layersh, "gtk_layer_auto_exclusive_zone_enable");
p_gtk_layer_init_for_window =
dlsym(dl_layersh, "gtk_layer_init_for_window");
p_gtk_layer_set_anchor =
dlsym(dl_layersh, "gtk_layer_set_anchor");
p_gtk_layer_set_layer =
dlsym(dl_layersh, "gtk_layer_set_layer");
p_gtk_layer_set_margin =
dlsym(dl_layersh, "gtk_layer_set_margin");
p_gtk_layer_set_monitor =
dlsym(dl_layersh, "gtk_layer_set_monitor");
p_gtk_layer_set_namespace =
dlsym(dl_layersh, "gtk_layer_set_namespace");
if (
p_gtk_layer_auto_exclusive_zone_enable == NULL ||
p_gtk_layer_init_for_window == NULL ||
p_gtk_layer_set_anchor == NULL ||
p_gtk_layer_set_layer == NULL ||
p_gtk_layer_set_margin == NULL ||
p_gtk_layer_set_monitor == NULL ||
p_gtk_layer_set_namespace == NULL
)
{
g_critical("%s", "Failed to resolve symbols for GTK layer shell.");
return FALSE;
}
s_initialized = TRUE;
return TRUE;
}

View File

@@ -0,0 +1,64 @@
#ifndef __DLL_LAYERSH_H__
#define __DLL_LAYERSH_H__
#include <glib.h>
//
// PUBLIC ENUMS
//
typedef enum
{
GTK_LAYER_SHELL_EDGE_LEFT = 0,
GTK_LAYER_SHELL_EDGE_RIGHT,
GTK_LAYER_SHELL_EDGE_TOP,
GTK_LAYER_SHELL_EDGE_BOTTOM,
GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER
} GtkLayerShellEdge;
typedef enum
{
GTK_LAYER_SHELL_LAYER_BACKGROUND = 0,
GTK_LAYER_SHELL_LAYER_BOTTOM,
GTK_LAYER_SHELL_LAYER_TOP,
GTK_LAYER_SHELL_LAYER_OVERLAY,
GTK_LAYER_SHELL_LAYER_ENTRY_NUMBER
} GtkLayerShellLayer;
//
// RESOLVED FUNCS
//
extern void (*p_gtk_layer_auto_exclusive_zone_enable) (
GtkWindow* window
);
extern void (*p_gtk_layer_init_for_window) (
GtkWindow* window
);
extern void (*p_gtk_layer_set_anchor) (
GtkWindow* window,
GtkLayerShellEdge edge,
gboolean anchor_to_edge
);
extern void (*p_gtk_layer_set_layer) (
GtkWindow* window,
GtkLayerShellLayer layer
);
extern void (*p_gtk_layer_set_margin) (
GtkWindow* window,
GtkLayerShellEdge edge,
int margin_size
);
extern void (*p_gtk_layer_set_monitor) (
GtkWindow* window,
GdkMonitor* monitor
);
extern void (*p_gtk_layer_set_namespace) (
GtkWindow* window,
const char* name_space
);
//
// PUBLIC FUNCTIONS
//
gboolean init_dll_layersh(void);
#endif

View File

@@ -5,55 +5,7 @@
#include "../public/api.h"
#include "impl-wayland.h"
//
// PRIVATE ENUMS
//
typedef enum
{
GTK_LAYER_SHELL_EDGE_LEFT = 0,
GTK_LAYER_SHELL_EDGE_RIGHT,
GTK_LAYER_SHELL_EDGE_TOP,
GTK_LAYER_SHELL_EDGE_BOTTOM,
GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER
} GtkLayerShellEdge;
typedef enum
{
GTK_LAYER_SHELL_LAYER_BACKGROUND = 0,
GTK_LAYER_SHELL_LAYER_BOTTOM,
GTK_LAYER_SHELL_LAYER_TOP,
GTK_LAYER_SHELL_LAYER_OVERLAY,
GTK_LAYER_SHELL_LAYER_ENTRY_NUMBER
} GtkLayerShellLayer;
//
// RESOLVED FUNCS
//
void (*p_gtk_layer_auto_exclusive_zone_enable) (
GtkWindow* window
);
void (*p_gtk_layer_init_for_window) (
GtkWindow* window
);
void (*p_gtk_layer_set_anchor) (
GtkWindow* window,
GtkLayerShellEdge edge,
gboolean anchor_to_edge
);
void (*p_gtk_layer_set_layer) (
GtkWindow* window,
GtkLayerShellLayer layer
);
void (*p_gtk_layer_set_margin) (
GtkWindow* window,
GtkLayerShellEdge edge,
int margin_size
);
void (*p_gtk_layer_set_namespace) (
GtkWindow* window,
const char* name_space
);
#include "dll/layersh.h"
//
// FORWARD DECLARATIONS
@@ -61,56 +13,20 @@ void (*p_gtk_layer_set_namespace) (
static void wayland_anchor_taskband_to_bottom(
GtkWindow* taskband
);
static void wayland_become_desktop_window(
GtkWindow* window
);
//
// PUBLIC FUNCTIONS
//
gboolean init_wayland_protocol_impl(void)
{
void* dl_gtk_layer_shell =
dlopen("libgtk-layer-shell.so", RTLD_LAZY | RTLD_LOCAL);
if (dl_gtk_layer_shell == NULL)
if (!init_dll_layersh())
{
g_critical("%s", "Failed to open libgtk-layer-shell for symbols.");
return FALSE;
}
// Resolve the funcs we're using
//
p_gtk_layer_auto_exclusive_zone_enable =
dlsym(dl_gtk_layer_shell, "gtk_layer_auto_exclusive_zone_enable");
p_gtk_layer_init_for_window =
dlsym(dl_gtk_layer_shell, "gtk_layer_init_for_window");
p_gtk_layer_set_anchor =
dlsym(dl_gtk_layer_shell, "gtk_layer_set_anchor");
p_gtk_layer_set_layer =
dlsym(dl_gtk_layer_shell, "gtk_layer_set_layer");
p_gtk_layer_set_margin =
dlsym(dl_gtk_layer_shell, "gtk_layer_set_margin");
p_gtk_layer_set_namespace =
dlsym(dl_gtk_layer_shell, "gtk_layer_set_namespace");
if (
p_gtk_layer_auto_exclusive_zone_enable == NULL ||
p_gtk_layer_init_for_window == NULL ||
p_gtk_layer_set_anchor == NULL ||
p_gtk_layer_set_layer == NULL ||
p_gtk_layer_set_margin == NULL ||
p_gtk_layer_set_namespace == NULL
)
{
g_critical("%s", "Failed to resolve symbols for GTK layer shell.");
return FALSE;
}
// All good, assign the API now
//
wintc_anchor_taskband_to_bottom = &wayland_anchor_taskband_to_bottom;
wintc_become_desktop_window = &wayland_become_desktop_window;
return TRUE;
}
@@ -133,16 +49,3 @@ static void wayland_anchor_taskband_to_bottom(
p_gtk_layer_set_anchor(taskband, i, anchors[i]);
}
}
static void wayland_become_desktop_window(
GtkWindow* window
)
{
p_gtk_layer_init_for_window(window);
p_gtk_layer_set_layer(window, GTK_LAYER_SHELL_LAYER_BACKGROUND);
p_gtk_layer_set_anchor(window, GTK_LAYER_SHELL_EDGE_TOP, TRUE);
p_gtk_layer_set_anchor(window, GTK_LAYER_SHELL_EDGE_LEFT, TRUE);
p_gtk_layer_set_margin(window, GTK_LAYER_SHELL_EDGE_TOP, 0);
p_gtk_layer_set_margin(window, GTK_LAYER_SHELL_EDGE_LEFT, 0);
p_gtk_layer_set_namespace(window, "desktop");
}

View File

@@ -35,9 +35,6 @@ struct X11Struts
static void x11_anchor_taskband_to_bottom(
GtkWindow* taskband
);
static void x11_become_desktop_window(
GtkWindow* window
);
static void on_taskband_realized(
GtkWidget* self,
@@ -50,7 +47,6 @@ static void on_taskband_realized(
gboolean init_x11_protocol_impl(void)
{
wintc_anchor_taskband_to_bottom = &x11_anchor_taskband_to_bottom;
wintc_become_desktop_window = &x11_become_desktop_window;
return TRUE;
}
@@ -70,51 +66,6 @@ static void x11_anchor_taskband_to_bottom(
);
}
static void x11_become_desktop_window(
GtkWindow* window
)
{
// Set up window size / position
//
GdkDisplay* display = gdk_display_get_default();
GdkRectangle geometry;
GdkMonitor* monitor = NULL;
int monitor_count = gdk_display_get_n_monitors(display);
gint work_height = 0;
gint work_width = 0;
for (int i = 0; i < monitor_count; i++)
{
gint bottom;
gint right;
monitor = gdk_display_get_monitor(display, i);
gdk_monitor_get_geometry(monitor, &geometry);
bottom = geometry.y + geometry.height;
right = geometry.x + geometry.width;
if (bottom > work_height)
{
work_height = bottom;
}
if (right > work_width)
{
work_width = right;
}
}
gtk_window_move(window, 0, 0);
gtk_window_set_type_hint(window, GDK_WINDOW_TYPE_HINT_DESKTOP);
gtk_widget_set_size_request(
GTK_WIDGET(window),
work_width,
work_height
);
}
//
// CALLBACKS
//