1
0
Fork 0
gdm3/daemon/gdm-display-store.c
Daniel Baumann 83b37a3d94
Adding upstream version 48.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 19:45:29 +02:00

327 lines
9.3 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include "gdm-display-store.h"
#include "gdm-display.h"
struct _GdmDisplayStore
{
GObject parent;
GHashTable *displays;
};
typedef struct
{
GdmDisplayStore *store;
GdmDisplay *display;
} StoredDisplay;
enum {
DISPLAY_ADDED,
DISPLAY_REMOVED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0, };
static void gdm_display_store_class_init (GdmDisplayStoreClass *klass);
static void gdm_display_store_init (GdmDisplayStore *display_store);
static void gdm_display_store_finalize (GObject *object);
G_DEFINE_TYPE (GdmDisplayStore, gdm_display_store, G_TYPE_OBJECT)
static StoredDisplay *
stored_display_new (GdmDisplayStore *store,
GdmDisplay *display)
{
StoredDisplay *stored_display;
stored_display = g_slice_new (StoredDisplay);
stored_display->store = store;
stored_display->display = g_object_ref (display);
return stored_display;
}
static void
stored_display_free (StoredDisplay *stored_display)
{
g_signal_emit (G_OBJECT (stored_display->store),
signals[DISPLAY_REMOVED],
0,
stored_display->display);
g_debug ("GdmDisplayStore: Unreffing display: %p",
stored_display->display);
g_object_unref (stored_display->display);
g_slice_free (StoredDisplay, stored_display);
}
GQuark
gdm_display_store_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_display_store_error");
}
return ret;
}
void
gdm_display_store_clear (GdmDisplayStore *store)
{
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
g_debug ("GdmDisplayStore: Clearing display store");
g_hash_table_remove_all (store->displays);
}
static gboolean
remove_display (char *id,
GdmDisplay *display,
GdmDisplay *display_to_remove)
{
if (display == display_to_remove) {
return TRUE;
}
return FALSE;
}
gboolean
gdm_display_store_remove (GdmDisplayStore *store,
GdmDisplay *display)
{
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), FALSE);
g_return_val_if_fail (display != NULL, FALSE);
gdm_display_store_foreach_remove (store,
(GdmDisplayStoreFunc)remove_display,
display);
return FALSE;
}
typedef struct
{
GdmDisplayStoreFunc predicate;
gpointer user_data;
} FindClosure;
static gboolean
find_func (const char *id,
StoredDisplay *stored_display,
FindClosure *closure)
{
return closure->predicate (id,
stored_display->display,
closure->user_data);
}
static void
foreach_func (const char *id,
StoredDisplay *stored_display,
FindClosure *closure)
{
(void) closure->predicate (id,
stored_display->display,
closure->user_data);
}
void
gdm_display_store_foreach (GdmDisplayStore *store,
GdmDisplayStoreFunc func,
gpointer user_data)
{
FindClosure closure;
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
g_return_if_fail (func != NULL);
closure.predicate = func;
closure.user_data = user_data;
g_hash_table_foreach (store->displays,
(GHFunc) foreach_func,
&closure);
}
GdmDisplay *
gdm_display_store_lookup (GdmDisplayStore *store,
const char *id)
{
StoredDisplay *stored_display;
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), NULL);
g_return_val_if_fail (id != NULL, NULL);
stored_display = g_hash_table_lookup (store->displays,
id);
if (stored_display == NULL) {
return NULL;
}
return stored_display->display;
}
GdmDisplay *
gdm_display_store_find (GdmDisplayStore *store,
GdmDisplayStoreFunc predicate,
gpointer user_data)
{
StoredDisplay *stored_display;
FindClosure closure;
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), NULL);
g_return_val_if_fail (predicate != NULL, NULL);
closure.predicate = predicate;
closure.user_data = user_data;
stored_display = g_hash_table_find (store->displays,
(GHRFunc) find_func,
&closure);
if (stored_display == NULL) {
return NULL;
}
return stored_display->display;
}
guint
gdm_display_store_foreach_remove (GdmDisplayStore *store,
GdmDisplayStoreFunc func,
gpointer user_data)
{
FindClosure closure;
guint ret;
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), 0);
g_return_val_if_fail (func != NULL, 0);
closure.predicate = func;
closure.user_data = user_data;
ret = g_hash_table_foreach_remove (store->displays,
(GHRFunc) find_func,
&closure);
return ret;
}
void
gdm_display_store_add (GdmDisplayStore *store,
GdmDisplay *display)
{
char *id;
StoredDisplay *stored_display;
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
g_return_if_fail (display != NULL);
gdm_display_get_id (display, &id, NULL);
g_debug ("GdmDisplayStore: Adding display %s to store", id);
stored_display = stored_display_new (store, display);
g_hash_table_insert (store->displays,
id,
stored_display);
g_signal_emit (G_OBJECT (store),
signals[DISPLAY_ADDED],
0,
id);
}
static void
gdm_display_store_class_init (GdmDisplayStoreClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdm_display_store_finalize;
signals [DISPLAY_ADDED] =
g_signal_new ("display-added",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1, G_TYPE_STRING);
signals [DISPLAY_REMOVED] =
g_signal_new ("display-removed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1, G_TYPE_OBJECT);
}
static void
gdm_display_store_init (GdmDisplayStore *store)
{
store->displays = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)
stored_display_free);
}
static void
gdm_display_store_finalize (GObject *object)
{
GdmDisplayStore *store;
g_return_if_fail (GDM_IS_DISPLAY_STORE (object));
store = GDM_DISPLAY_STORE (object);
g_hash_table_destroy (store->displays);
G_OBJECT_CLASS (gdm_display_store_parent_class)->finalize (object);
}
GdmDisplayStore *
gdm_display_store_new (void)
{
GObject *object;
object = g_object_new (GDM_TYPE_DISPLAY_STORE,
NULL);
return GDM_DISPLAY_STORE (object);
}