Introduce GdkToplevel

This is a new interface for toplevel surfaces.
This commit is contained in:
Matthias Clasen 2020-02-29 10:07:43 -05:00
parent c0c387020b
commit dfbde3da4f
6 changed files with 937 additions and 21 deletions

View File

@ -27,12 +27,11 @@
#define __GDK_H_INSIDE__
#include <gdk/gdkconfig.h>
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkapplaunchcontext.h>
#include <gdk/gdkcairo.h>
#include <gdk/gdkcairocontext.h>
#include <gdk/gdkclipboard.h>
#include <gdk/gdkconfig.h>
#include <gdk/gdkcontentdeserializer.h>
#include <gdk/gdkcontentformats.h>
#include <gdk/gdkcontentprovider.h>
@ -60,16 +59,19 @@
#include <gdk/gdkpaintable.h>
#include <gdk/gdkpango.h>
#include <gdk/gdkpixbuf.h>
#include <gdk/gdkpopup.h>
#include <gdk/gdkpopuplayout.h>
#include <gdk/gdkrectangle.h>
#include <gdk/gdkrgba.h>
#include <gdk/gdkseat.h>
#include <gdk/gdksnapshot.h>
#include <gdk/gdktexture.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkvulkancontext.h>
#include <gdk/gdksurface.h>
#include <gdk/gdkpopup.h>
#include <gdk/gdktexture.h>
#include <gdk/gdktoplevel.h>
#include <gdk/gdktoplevellayout.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkvulkancontext.h>
#include <gdk/gdk-autocleanup.h>

View File

@ -40,6 +40,7 @@
#include "gdkmarshalers.h"
#include "gdkpopupprivate.h"
#include "gdkrectangle.h"
#include "gdktoplevelprivate.h"
#include <math.h>
@ -83,7 +84,6 @@ enum {
PROP_CURSOR,
PROP_DISPLAY,
PROP_FRAME_CLOCK,
PROP_STATE,
PROP_MAPPED,
LAST_PROP
};
@ -112,10 +112,13 @@ static guint signals[LAST_SIGNAL] = { 0 };
static GParamSpec *properties[LAST_PROP] = { NULL, };
static void gdk_surface_popup_init (GdkPopupInterface *iface);
static void gdk_surface_toplevel_init (GdkToplevelInterface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkSurface, gdk_surface, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP,
gdk_surface_popup_init))
gdk_surface_popup_init)
G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL,
gdk_surface_toplevel_init))
static gboolean
gdk_surface_real_beep (GdkSurface *surface)
@ -443,13 +446,6 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
GDK_TYPE_FRAME_CLOCK,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
properties[PROP_STATE] =
g_param_spec_flags ("state",
P_("State"),
P_("State"),
GDK_TYPE_SURFACE_STATE, GDK_SURFACE_STATE_WITHDRAWN,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_MAPPED] =
g_param_spec_boolean ("mapped",
P_("Mapped"),
@ -466,6 +462,7 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
g_object_class_install_properties (object_class, LAST_PROP, properties);
gdk_popup_install_properties (object_class, LAST_PROP);
gdk_toplevel_install_properties (object_class, LAST_PROP + GDK_POPUP_NUM_PROPERTIES);
/**
* GdkSurface::popup-layout-changed
@ -644,12 +641,81 @@ gdk_surface_set_property (GObject *object,
surface->autohide = g_value_get_boolean (value);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_TITLE:
gdk_surface_set_title (surface, g_value_get_string (value));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_STARTUP_ID:
gdk_surface_set_startup_id (surface, g_value_get_string (value));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
gdk_surface_set_transient_for (surface, g_value_get_object (value));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_MODAL:
GDK_SURFACE_GET_CLASS (surface)->set_modal_hint (surface, g_value_get_boolean (value));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_ICON_LIST:
gdk_surface_set_icon_list (surface, g_value_get_pointer (value));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_STICKY:
if (g_value_get_boolean (value))
GDK_SURFACE_GET_CLASS (surface)->stick (surface);
else
GDK_SURFACE_GET_CLASS (surface)->unstick (surface);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_KEEP_ABOVE:
GDK_SURFACE_GET_CLASS (surface)->set_keep_above (surface, g_value_get_boolean (value));
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_KEEP_BELOW:
GDK_SURFACE_GET_CLASS (surface)->set_keep_below (surface, g_value_get_boolean (value));
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_ACCEPT_FOCUS:
if (surface->accept_focus != g_value_get_boolean (value))
{
surface->accept_focus = g_value_get_boolean (value);
GDK_SURFACE_GET_CLASS (surface)->set_accept_focus (surface, surface->accept_focus);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
}
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_FOCUS_ON_MAP:
if (surface->focus_on_map != g_value_get_boolean (value))
{
surface->focus_on_map = g_value_get_boolean (value);
GDK_SURFACE_GET_CLASS (surface)->set_focus_on_map (surface, surface->focus_on_map);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
}
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_DECORATED:
GDK_SURFACE_GET_CLASS (surface)->set_decorations (surface, g_value_get_boolean (value) ? GDK_DECOR_ALL : 0);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_DELETABLE:
GDK_SURFACE_GET_CLASS (surface)->set_functions (surface, g_value_get_boolean (value) ? GDK_FUNC_ALL : GDK_FUNC_ALL | GDK_FUNC_CLOSE);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
#define GDK_SURFACE_IS_STICKY(surface) (((surface)->state & GDK_SURFACE_STATE_STICKY))
#define GDK_SURFACE_IS_ABOVE(surface) (((surface)->state & GDK_SURFACE_STATE_ABOVE))
#define GDK_SURFACE_IS_BELOW(surface) (((surface)->state & GDK_SURFACE_STATE_BELOW))
static void
gdk_surface_get_property (GObject *object,
guint prop_id,
@ -672,10 +738,6 @@ gdk_surface_get_property (GObject *object,
g_value_set_object (value, surface->frame_clock);
break;
case PROP_STATE:
g_value_set_flags (value, surface->state);
break;
case PROP_MAPPED:
g_value_set_boolean (value, GDK_SURFACE_IS_MAPPED (surface));
break;
@ -692,6 +754,58 @@ gdk_surface_get_property (GObject *object,
g_value_set_boolean (value, surface->autohide);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_STATE:
g_value_set_flags (value, surface->state);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_TITLE:
g_value_set_string (value, ""); // FIXME
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_STARTUP_ID:
g_value_set_string (value, ""); // FIXME
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
g_value_set_object (value, NULL); // FIXME
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_MODAL:
g_value_set_boolean (value, surface->modal_hint);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_ICON_LIST:
g_value_set_pointer (value, NULL); // FIXME
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_STICKY:
g_value_set_boolean (value, GDK_SURFACE_IS_STICKY (surface));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_KEEP_ABOVE:
g_value_set_boolean (value, GDK_SURFACE_IS_ABOVE (surface));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_KEEP_BELOW:
g_value_set_boolean (value, GDK_SURFACE_IS_BELOW (surface));
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_ACCEPT_FOCUS:
g_value_set_boolean (value, surface->accept_focus);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_FOCUS_ON_MAP:
g_value_set_boolean (value, surface->focus_on_map);
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_DECORATED:
g_value_set_boolean (value, FALSE); // FIXME
break;
case LAST_PROP + GDK_POPUP_NUM_PROPERTIES + GDK_TOPLEVEL_PROP_DELETABLE:
g_value_set_boolean (value, FALSE); // FIXME
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -867,7 +981,8 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface,
surface_remove_from_pointer_info (surface, surface->display);
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
if (GDK_IS_TOPLEVEL (surface))
g_object_notify (G_OBJECT (surface), "state");
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
}
@ -2078,6 +2193,116 @@ gdk_surface_popup_init (GdkPopupInterface *iface)
iface->get_position_y = gdk_popup_surface_get_position_y;
}
static gboolean
gdk_toplevel_surface_present (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkGeometry geometry;
GdkSurfaceHints mask;
g_return_val_if_fail (surface->surface_type == GDK_SURFACE_TOPLEVEL, FALSE);
g_return_val_if_fail (!GDK_SURFACE_DESTROYED (surface), FALSE);
GDK_SURFACE_GET_CLASS (surface)->unminimize (surface);
if (gdk_toplevel_layout_get_resizable (layout))
{
geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
mask = GDK_HINT_MIN_SIZE;
}
else
{
geometry.max_width = geometry.min_width = width;
geometry.max_height = geometry.min_height = height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
}
GDK_SURFACE_GET_CLASS (surface)->set_geometry_hints (surface, &geometry, mask);
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
GDK_SURFACE_GET_CLASS (surface)->toplevel_resize (surface, width, height);
if (gdk_toplevel_layout_get_maximized (layout))
gdk_surface_maximize (surface);
else
gdk_surface_unmaximize (surface);
if (gdk_toplevel_layout_get_fullscreen (layout))
{
GdkMonitor *monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout);
if (monitor)
GDK_SURFACE_GET_CLASS (surface)->fullscreen_on_monitor (surface, monitor);
else
GDK_SURFACE_GET_CLASS (surface)->fullscreen (surface);
}
else
GDK_SURFACE_GET_CLASS (surface)->unfullscreen (surface);
gdk_surface_show_internal (surface, TRUE);
return TRUE;
}
static gboolean
gdk_toplevel_surface_minimize (GdkToplevel *toplevel)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
g_return_val_if_fail (surface->surface_type == GDK_SURFACE_TOPLEVEL, FALSE);
GDK_SURFACE_GET_CLASS (surface)->minimize (surface);
return TRUE;
}
static gboolean
gdk_toplevel_surface_lower (GdkToplevel *toplevel)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
g_return_val_if_fail (surface->surface_type == GDK_SURFACE_TOPLEVEL, FALSE);
GDK_SURFACE_GET_CLASS (surface)->lower (surface);
return TRUE;
}
static void
gdk_toplevel_surface_focus (GdkToplevel *toplevel,
guint32 timestamp)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
g_return_if_fail (surface->surface_type == GDK_SURFACE_TOPLEVEL);
GDK_SURFACE_GET_CLASS (surface)->focus (surface, timestamp);
}
static gboolean
gdk_toplevel_surface_show_window_menu (GdkToplevel *toplevel,
GdkEvent *event)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
g_return_val_if_fail (surface->surface_type == GDK_SURFACE_TOPLEVEL, FALSE);
return GDK_SURFACE_GET_CLASS (surface)->show_window_menu (surface, event);
}
static void
gdk_surface_toplevel_init (GdkToplevelInterface *iface)
{
iface->present = gdk_toplevel_surface_present;
iface->minimize = gdk_toplevel_surface_minimize;
iface->lower = gdk_toplevel_surface_lower;
iface->focus = gdk_toplevel_surface_focus;
iface->show_window_menu = gdk_toplevel_surface_show_window_menu;
}
static void
gdk_surface_set_cursor_internal (GdkSurface *surface,
GdkDevice *device,
@ -2867,6 +3092,8 @@ gdk_surface_set_startup_id (GdkSurface *surface,
const gchar *startup_id)
{
GDK_SURFACE_GET_CLASS (surface)->set_startup_id (surface, startup_id);
g_object_notify (G_OBJECT (surface), "startup-id");
}
/**
@ -2889,6 +3116,8 @@ gdk_surface_set_transient_for (GdkSurface *surface,
surface->transient_for = parent;
GDK_SURFACE_GET_CLASS (surface)->set_transient_for (surface, parent);
g_object_notify (G_OBJECT (surface), "transient-for");
}
/**
@ -2951,6 +3180,8 @@ gdk_surface_set_icon_list (GdkSurface *surface,
GList *textures)
{
GDK_SURFACE_GET_CLASS (surface)->set_icon_list (surface, textures);
g_object_notify (G_OBJECT (surface), "icon-list");
}
/**
@ -3790,6 +4021,7 @@ gdk_surface_set_state (GdkSurface *surface,
GdkSurfaceState new_state)
{
gboolean was_mapped, mapped;
gboolean was_sticky, sticky;
g_return_if_fail (GDK_IS_SURFACE (surface));
if (new_state == surface->state)
@ -3801,17 +4033,23 @@ gdk_surface_set_state (GdkSurface *surface,
*/
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
was_sticky = GDK_SURFACE_IS_STICKY (surface);
surface->state = new_state;
mapped = GDK_SURFACE_IS_MAPPED (surface);
sticky = GDK_SURFACE_IS_STICKY (surface);
_gdk_surface_update_viewable (surface);
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_STATE]);
if (GDK_IS_TOPLEVEL (surface))
g_object_notify (G_OBJECT (surface), "state");
if (was_mapped != mapped)
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
if (was_sticky != sticky)
g_object_notify (G_OBJECT (surface), "sticky");
}
void

518
gdk/gdktoplevel.c Normal file
View File

@ -0,0 +1,518 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "gdkintl.h"
#include "gdk-private.h"
#include "gdktoplevelprivate.h"
/**
* SECTION:gdktoplevel
* @Short_description: Interface for toplevel surfaces
* @Title: Toplevels
*
* A #GdkToplevel is a freestanding toplevel surface.
*/
/* FIXME: this can't have GdkSurface as a prerequisite
* as long as GdkSurface implements this interface itself
*/
G_DEFINE_INTERFACE (GdkToplevel, gdk_toplevel, G_TYPE_OBJECT)
static gboolean
gdk_toplevel_default_present (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout)
{
return FALSE;
}
static gboolean
gdk_toplevel_default_minimize (GdkToplevel *toplevel)
{
return FALSE;
}
static gboolean
gdk_toplevel_default_lower (GdkToplevel *toplevel)
{
return FALSE;
}
static void
gdk_toplevel_default_focus (GdkToplevel *toplevel,
guint32 timestamp)
{
}
static gboolean
gdk_toplevel_default_show_window_menu (GdkToplevel *toplevel,
GdkEvent *event)
{
return FALSE;
}
static void
gdk_toplevel_default_init (GdkToplevelInterface *iface)
{
iface->present = gdk_toplevel_default_present;
iface->minimize = gdk_toplevel_default_minimize;
iface->lower = gdk_toplevel_default_lower;
iface->focus = gdk_toplevel_default_focus;
iface->show_window_menu = gdk_toplevel_default_show_window_menu;
g_object_interface_install_property (iface,
g_param_spec_flags ("state",
P_("State"),
P_("State"),
GDK_TYPE_SURFACE_STATE, GDK_SURFACE_STATE_WITHDRAWN,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_string ("title",
"Title",
"The title of the surface",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_string ("startup-id",
"Startup ID",
"The startup ID of the surface",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_object ("transient-for",
"Transient For",
"The transient parent of the surface",
GDK_TYPE_SURFACE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("modal",
"Modal",
"Whether the surface is modal",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_pointer ("icon-list",
"Icon List",
"The list of icon textures",
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("sticky",
"Sticky",
"Whether the surface is on all workspaces",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("keep-above",
"Keep above",
"Whether the surface is on above all other surfaces",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("keep-below",
"Keep below",
"Whether the surface is below all other surfaces",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("accept-focus",
"Accept focus",
"Whether the surface should accept keyboard focus",
TRUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("focus-on-map",
"Focus on map",
"Whether the surface should receive keyboard focus on map",
TRUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("decorated",
"Decorated",
"Decorated",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
g_object_interface_install_property (iface,
g_param_spec_boolean ("deletable",
"Deletable",
"Deletable",
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
}
guint
gdk_toplevel_install_properties (GObjectClass *object_class,
guint first_prop)
{
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_STATE, "state");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_TITLE, "title");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_STARTUP_ID, "startup-id");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_TRANSIENT_FOR, "transient-for");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_MODAL, "modal");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_ICON_LIST, "icon-list");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_STICKY, "sticky");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_KEEP_ABOVE, "keep-above");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_KEEP_BELOW, "keep-below");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_ACCEPT_FOCUS, "accept-focus");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_FOCUS_ON_MAP, "focus-on-map");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DECORATED, "decorated");
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DELETABLE, "deletable");
return GDK_TOPLEVEL_NUM_PROPERTIES;
}
/**
* gdk_toplevel_present:
* @toplevel: the #GdkToplevel to show
* @width: the unconstrained toplevel width to layout
* @height: the unconstrained toplevel height to layout
* @layout: the #GdkToplevelLayout object used to layout
*
* Present @toplevel after having processed the #GdkToplevelLayout rules.
* If the toplevel was previously now showing, it will be showed,
* otherwise it will change layout according to @layout.
*
* Presenting may fail.
*
* Returns: %FALSE if @toplevel failed to be presented, otherwise %TRUE.
*/
gboolean
gdk_toplevel_present (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
g_return_val_if_fail (width > 0, FALSE);
g_return_val_if_fail (height > 0, FALSE);
g_return_val_if_fail (layout != NULL, FALSE);
return GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, width, height, layout);
}
/**
* gdk_toplevel_minimize:
* @toplevel: a #GdkToplevel
*
* Asks to minimize the @toplevel.
*
* The windowing system may choose to ignore the request.
*
* Returns: %TRUE if the surface was minimized
*/
gboolean
gdk_toplevel_minimize (GdkToplevel *toplevel)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
return GDK_TOPLEVEL_GET_IFACE (toplevel)->minimize (toplevel);
}
/**
* gdk_toplevel_lower:
* @toplevel: a #GdkToplevel
*
* Asks to lower the @toplevel below other windows.
*
* The windowing system may choose to ignore the request.
*
* Returns: %TRUE if the surface was lowered
*/
gboolean
gdk_toplevel_lower (GdkToplevel *toplevel)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
return GDK_TOPLEVEL_GET_IFACE (toplevel)->lower (toplevel);
}
/**
* gdk_toplevel_focus:
* @toplevel: a #GdkToplevel
* @timestamp: timestamp of the event triggering the surface focus
*
* Sets keyboard focus to @surface.
*
* In most cases, gtk_window_present_with_time() should be used
* on a #GtkWindow, rather than calling this function.
*/
void
gdk_toplevel_focus (GdkToplevel *toplevel,
guint32 timestamp)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
return GDK_TOPLEVEL_GET_IFACE (toplevel)->focus (toplevel, timestamp);
}
/**
* gdk_toplevel_get_state:
* @toplevel: a #GdkToplevel
*
* Gets the bitwise OR of the currently active surface state flags,
* from the #GdkSurfaceState enumeration.
*
* Returns: surface state bitfield
*/
GdkSurfaceState
gdk_toplevel_get_state (GdkToplevel *toplevel)
{
GdkSurfaceState state;
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), 0);
g_object_get (toplevel, "state", &state, NULL);
return state;
}
/**
* gdk_toplevel_set_title:
* @toplevel: a #GdkToplevel
* @title: title of @surface
*
* Sets the title of a toplevel surface, to be displayed in the titlebar,
* in lists of windows, etc.
*/
void
gdk_toplevel_set_title (GdkToplevel *toplevel,
const char *title)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "title", title, NULL);
}
/**
* gdk_toplevel_set_startup_id:
* @toplevel: a #GdkToplevel
* @startup_id: a string with startup-notification identifier
*
* When using GTK, typically you should use gtk_window_set_startup_id()
* instead of this low-level function.
*/
void
gdk_toplevel_set_startup_id (GdkToplevel *toplevel,
const char *startup_id)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "startup-id", startup_id, NULL);
}
/**
* gdk_toplevel_set_transient_for:
* @toplevel: a #GdkToplevel
* @parent: another toplevel #GdkSurface
*
* Indicates to the window manager that @surface is a transient dialog
* associated with the application surface @parent. This allows the
* window manager to do things like center @surface on @parent and
* keep @surface above @parent.
*
* See gtk_window_set_transient_for() if youre using #GtkWindow or
* #GtkDialog.
*/
void
gdk_toplevel_set_transient_for (GdkToplevel *toplevel,
GdkSurface *parent)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "transient-for", parent, NULL);
}
void
gdk_toplevel_set_modal (GdkToplevel *toplevel,
gboolean modal)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "modal", modal, NULL);
}
/**
* gdk_toplevel_set_icon_list:
* @toplevel: a #GdkToplevel
* @surfaces: (transfer none) (element-type GdkTexture):
* A list of textures to use as icon, of different sizes
*
* Sets a list of icons for the surface.
*
* One of these will be used to represent the surface in iconic form.
* The icon may be shown in window lists or task bars. Which icon
* size is shown depends on the window manager. The window manager
* can scale the icon but setting several size icons can give better
* image quality.
*
* Note that some platforms don't support surface icons.
*/
void
gdk_toplevel_set_icon_list (GdkToplevel *toplevel,
GList *surfaces)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "icon-list", surfaces, NULL);
}
/**
* gdk_toplevel_show_window_menu:
* @toplevel: a #GdkToplevel
* @event: a #GdkEvent to show the menu for
*
* Asks the windowing system to show the window menu.
*
* The window menu is the menu shown when right-clicking the titlebar
* on traditional windows managed by the window manager. This is useful
* for windows using client-side decorations, activating it with a
* right-click on the window decorations.
*
* Returns: %TRUE if the window menu was shown and %FALSE otherwise.
*/
gboolean
gdk_toplevel_show_window_menu (GdkToplevel *toplevel,
GdkEvent *event)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
return GDK_TOPLEVEL_GET_IFACE (toplevel)->show_window_menu (toplevel, event);
}
/**
* gdk_toplevel_set_sticky:
* @toplevel: a #GdkToplevel
* @sticky: whether to make @toplevel show on all workspaces
*
* Set if @surface is sticky.
**/
void
gdk_toplevel_set_sticky (GdkToplevel *toplevel,
gboolean sticky)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "sticky", sticky, NULL);
}
/**
* gdk_toplevel_set_keep_above:
* @toplevel: a #GdkToplevel
* @above: whether to keep @toplevel above other surfaces
*
* Set if @surface must be kept above other surfaces.
**/
void
gdk_toplevel_set_keep_above (GdkToplevel *toplevel,
gboolean above)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "keep-above", above, NULL);
}
/**
* gdk_toplevel_set_keep_below:
* @toplevel: a #GdkToplevel
* @below: whether to keep @toplevel below other surfaces
*
* Set if @surface must be kept below other surfaces.
**/
void
gdk_toplevel_set_keep_below (GdkToplevel *toplevel,
gboolean below)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "keep-below", below, NULL);
}
/**
* gdk_toplevel_set_accept_focus:
* @toplevel: a #GdkToplevel
* @accept_focus: whether @toplevel should accept keyboard focus
*
* Setting @accept_focus to %FALSE hints the desktop environment
* that the surface doesnt want to receive input focus.
*/
void
gdk_toplevel_set_accept_focus (GdkToplevel *toplevel,
gboolean accept_focus)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "accept-focus", accept_focus, NULL);
}
/**
* gdk_toplevel_set_focus_on_map:
* @toplevel: a #GdkToplevel
* @focus_on_map: whether @toplevel should receive input focus when mapped
*
* Setting @focus_on_map to %FALSE hints the desktop environment that the
* surface doesnt want to receive input focus when it is mapped.
* focus_on_map should be turned off for surfaces that arent triggered
* interactively (such as popups from network activity).
*/
void
gdk_toplevel_set_focus_on_map (GdkToplevel *toplevel,
gboolean focus_on_map)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "focus-on-map", focus_on_map, NULL);
}
/**
* gdk_toplevel_set_decorated:
* @toplevel: a #GdkToplevel
* @decorated: %TRUE to request decorations
*
* Setting @decorated to %FALSE hints the desktop environment
* that the surface has its own, client-side decorations and
* does not need to have window decorations added.
*/
void
gdk_toplevel_set_decorated (GdkToplevel *toplevel,
gboolean decorated)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "decorated", decorated, NULL);
}
/**
* gdk_toplevel_set_deletable:
* @toplevel: a #GdkToplevel
* @deletable: %TRUE to request a delete button
*
* Setting @deletable to %TRUE hints the desktop environment
* that it should offer the user a way to close the surface.
*/
void
gdk_toplevel_set_deletable (GdkToplevel *toplevel,
gboolean deletable)
{
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
g_object_set (toplevel, "deletable", deletable, NULL);
}

108
gdk/gdktoplevel.h Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#ifndef __GDK_TOPLEVEL_H__
#define __GDK_TOPLEVEL_H__
#if !defined(__GDK_H_INSIDE__) && !defined(GTK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#include <gdk/gdksurface.h>
#include <gdk/gdktoplevellayout.h>
G_BEGIN_DECLS
#define GDK_TYPE_TOPLEVEL (gdk_toplevel_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (GdkToplevel, gdk_toplevel, GDK, TOPLEVEL, GObject)
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_present (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout);
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_minimize (GdkToplevel *toplevel);
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_lower (GdkToplevel *toplevel);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_focus (GdkToplevel *toplevel,
guint32 timestamp);
GDK_AVAILABLE_IN_ALL
GdkSurfaceState gdk_toplevel_get_state (GdkToplevel *toplevel);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_title (GdkToplevel *toplevel,
const char *title);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_startup_id (GdkToplevel *toplevel,
const char *startup_id);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_transient_for (GdkToplevel *toplevel,
GdkSurface *parent);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_modal (GdkToplevel *toplevel,
gboolean modal);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_icon_list (GdkToplevel *toplevel,
GList *surfaces);
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_show_window_menu (GdkToplevel *toplevel,
GdkEvent *event);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_sticky (GdkToplevel *toplevel,
gboolean sticky);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_keep_above (GdkToplevel *toplevel,
gboolean above);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_keep_below (GdkToplevel *toplevel,
gboolean below);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_accept_focus (GdkToplevel *toplevel,
gboolean accept_focus);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_focus_on_map (GdkToplevel *toplevel,
gboolean focus_on_map);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_decorated (GdkToplevel *toplevel,
gboolean decorated);
GDK_AVAILABLE_IN_ALL
void gdk_toplevel_set_deletable (GdkToplevel *toplevel,
gboolean deletable);
G_END_DECLS
#endif /* __GDK_TOPLEVEL_H__ */

48
gdk/gdktoplevelprivate.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef __GDK_TOPLEVEL_PRIVATE_H__
#define __GDK_TOPLEVEL_PRIVATE_H__
#include "gdktoplevel.h"
G_BEGIN_DECLS
struct _GdkToplevelInterface
{
GTypeInterface g_iface;
gboolean (* present) (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout);
gboolean (* minimize) (GdkToplevel *toplevel);
gboolean (* lower) (GdkToplevel *toplevel);
void (* focus) (GdkToplevel *toplevel,
guint32 timestamp);
gboolean (* show_window_menu) (GdkToplevel *toplevel,
GdkEvent *event);
};
typedef enum
{
GDK_TOPLEVEL_PROP_STATE,
GDK_TOPLEVEL_PROP_TITLE,
GDK_TOPLEVEL_PROP_STARTUP_ID,
GDK_TOPLEVEL_PROP_TRANSIENT_FOR,
GDK_TOPLEVEL_PROP_MODAL,
GDK_TOPLEVEL_PROP_ICON_LIST,
GDK_TOPLEVEL_PROP_STICKY,
GDK_TOPLEVEL_PROP_KEEP_ABOVE,
GDK_TOPLEVEL_PROP_KEEP_BELOW,
GDK_TOPLEVEL_PROP_ACCEPT_FOCUS,
GDK_TOPLEVEL_PROP_FOCUS_ON_MAP,
GDK_TOPLEVEL_PROP_DECORATED,
GDK_TOPLEVEL_PROP_DELETABLE,
GDK_TOPLEVEL_NUM_PROPERTIES
} GdkToplevelProperties;
guint gdk_toplevel_install_properties (GObjectClass *object_class,
guint first_prop);
G_END_DECLS
#endif /* __GDK_TOPLEVEL_PRIVATE_H__ */

View File

@ -47,6 +47,7 @@ gdk_public_sources = files([
'gdkprofiler.c',
'gdkpopup.c',
'gdktoplevellayout.c',
'gdktoplevel.c',
])
gdk_public_headers = files([
@ -93,6 +94,7 @@ gdk_public_headers = files([
'gdkpopuplayout.h',
'gdkpopup.h',
'gdktoplevellayout.h',
'gdktoplevel.h',
])
install_headers(gdk_public_headers, subdir: 'gtk-4.0/gdk/')