Back to index

lightdm  1.3.2
x-server.c
Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- */
00002 
00003 #include <stdlib.h>
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <errno.h>
00007 #include <sys/types.h>
00008 #include <sys/socket.h>
00009 #include <glib.h>
00010 #include <gio/gio.h>
00011 #include <gio/gunixsocketaddress.h>
00012 
00013 #include "x-common.h"
00014 #include "x-server.h"
00015 
00016 G_DEFINE_TYPE (XServer, x_server, G_TYPE_OBJECT);
00017 G_DEFINE_TYPE (XScreen, x_screen, G_TYPE_OBJECT);
00018 G_DEFINE_TYPE (XVisual, x_visual, G_TYPE_OBJECT);
00019 G_DEFINE_TYPE (XClient, x_client, G_TYPE_OBJECT);
00020 
00021 #define MAXIMUM_REQUEST_LENGTH 65535
00022 
00023 enum
00024 {
00025     Failed = 0,
00026     Success = 1,
00027     Authenticate = 2
00028 };
00029 
00030 enum
00031 {
00032     Error = 0,
00033     Reply = 1,
00034 };
00035 
00036 enum
00037 {
00038     InternAtom = 16,
00039     GetProperty = 20,
00040     QueryExtension = 98,
00041     kbUseExtension = 200
00042 };
00043 
00044 enum
00045 {
00046     BadAtom = 5,
00047     BadImplementation = 17
00048 };
00049 
00050 enum {
00051     X_SERVER_CLIENT_CONNECTED,
00052     X_SERVER_CLIENT_DISCONNECTED,
00053     X_SERVER_LAST_SIGNAL
00054 };
00055 static guint x_server_signals[X_SERVER_LAST_SIGNAL] = { 0 };
00056 
00057 typedef struct
00058 {
00059     guint8 depth;
00060     guint8 bits_per_pixel;
00061     guint8 scanline_pad;
00062 } PixmapFormat;
00063 
00064 struct XServerPrivate
00065 {
00066     gchar *vendor;
00067 
00068     gint display_number;
00069   
00070     guint32 motion_buffer_size;
00071     guint8 image_byte_order;
00072     guint8 bitmap_format_bit_order;
00073   
00074     guint8 min_keycode;
00075     guint8 max_keycode;
00076 
00077     GList *pixmap_formats;  
00078     GList *screens;
00079 
00080     gboolean listen_unix;
00081     gboolean listen_tcp;
00082     gint tcp_port;
00083     gchar *socket_path;
00084     GSocket *unix_socket;
00085     GIOChannel *unix_channel;
00086     GSocket *tcp_socket;
00087     GIOChannel *tcp_channel;
00088     GHashTable *clients;
00089     GHashTable *atoms;
00090     gint next_atom_index;
00091 };
00092 
00093 struct XClientPrivate
00094 {
00095     XServer *server;
00096     GSocket *socket;  
00097     GIOChannel *channel;
00098     guint8 byte_order;
00099     gboolean connected;
00100     guint16 sequence_number;
00101 };
00102 
00103 struct XScreenPrivate
00104 {
00105     guint32 white_pixel;
00106     guint32 black_pixel;
00107     guint32 current_input_masks;
00108     guint16 width_in_pixels;
00109     guint16 height_in_pixels;
00110     guint16 width_in_millimeters;
00111     guint16 height_in_millimeters;
00112     GList *visuals;
00113 };
00114 
00115 struct XVisualPrivate
00116 {
00117     guint32 id;
00118     guint8 depth;
00119     guint8 class;
00120     guint8 bits_per_rgb_value;
00121     guint16 colormap_entries;
00122     guint32 red_mask;
00123     guint32 green_mask;
00124     guint32 blue_mask;
00125 };
00126 
00127 enum
00128 {
00129     X_CLIENT_CONNECT,
00130     X_CLIENT_DISCONNECTED,
00131     X_CLIENT_LAST_SIGNAL
00132 };
00133 static guint x_client_signals[X_CLIENT_LAST_SIGNAL] = { 0 };
00134 
00135 GInetAddress *
00136 x_client_get_address (XClient *client)
00137 {
00138     GSocketAddress *socket_address;
00139     GError *error = NULL;
00140 
00141     socket_address = g_socket_get_remote_address (client->priv->socket, &error);
00142     if (error)
00143         g_warning ("Error getting remote socket address");
00144     g_clear_error (&error);
00145     if (!socket_address)
00146         return NULL;
00147 
00148     if (G_IS_INET_SOCKET_ADDRESS (socket_address))
00149         return g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
00150     else
00151         return NULL;
00152 }
00153 
00154 void
00155 x_client_send_failed (XClient *client, const gchar *reason)
00156 {
00157     guint8 buffer[MAXIMUM_REQUEST_LENGTH];
00158     gsize n_written = 0, length_offset;
00159 
00160     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, Failed, &n_written);
00161     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, strlen (reason), &n_written);
00162     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, X_PROTOCOL_MAJOR_VERSION, &n_written);
00163     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, X_PROTOCOL_MINOR_VERSION, &n_written);
00164     length_offset = n_written;
00165     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written);
00166     write_padded_string (buffer, MAXIMUM_REQUEST_LENGTH, reason, &n_written);
00167 
00168     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, (n_written - length_offset) / 4, &length_offset);
00169 
00170     send (g_io_channel_unix_get_fd (client->priv->channel), buffer, n_written, 0);
00171 }
00172 
00173 void 
00174 x_client_send_success (XClient *client)
00175 {
00176     XServer *server = client->priv->server;
00177     guint8 buffer[MAXIMUM_REQUEST_LENGTH];
00178     gsize n_written = 0, length_offset;
00179     GList *link;
00180 
00181     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, Success, &n_written);
00182     write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written);
00183     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, X_PROTOCOL_MAJOR_VERSION, &n_written);
00184     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, X_PROTOCOL_MINOR_VERSION, &n_written);
00185     length_offset = n_written;
00186     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written);
00187     write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, X_RELEASE_NUMBER, &n_written);
00188     write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0x00a00000, &n_written); // resource-id-base
00189     write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0x001fffff, &n_written); // resource-id-mask
00190     write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, server->priv->motion_buffer_size, &n_written);
00191     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, strlen (client->priv->server->priv->vendor), &n_written);
00192     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, MAXIMUM_REQUEST_LENGTH, &n_written);
00193     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, g_list_length (server->priv->screens), &n_written);
00194     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, g_list_length (server->priv->pixmap_formats), &n_written);
00195     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, server->priv->image_byte_order, &n_written);
00196     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, server->priv->bitmap_format_bit_order, &n_written);
00197     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 32, &n_written); // bitmap-format-scanline-unit
00198     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 32, &n_written); // bitmap-format-scanline-pad
00199     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, server->priv->min_keycode, &n_written);
00200     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, server->priv->max_keycode, &n_written);
00201     write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 4, &n_written);
00202     write_padded_string (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->server->priv->vendor, &n_written);
00203 
00204     for (link = server->priv->pixmap_formats; link; link = link->next)
00205     {
00206         PixmapFormat *format = link->data;
00207         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, format->depth, &n_written);
00208         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, format->bits_per_pixel, &n_written);
00209         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, format->scanline_pad, &n_written);
00210         write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 5, &n_written);
00211     }
00212 
00213     for (link = server->priv->screens; link; link = link->next)
00214     {
00215         XScreen *screen = link->data;
00216         guint8 depth, n_depths = 0;
00217         gsize n_depths_offset;
00218 
00219         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 87, &n_written); // root
00220         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 32, &n_written); // default-colormap
00221         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->white_pixel, &n_written);
00222         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->black_pixel, &n_written);
00223         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->current_input_masks, &n_written);
00224         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->width_in_pixels, &n_written);
00225         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->height_in_pixels, &n_written);
00226         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->width_in_millimeters, &n_written);
00227         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, screen->priv->height_in_millimeters, &n_written);
00228         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 1, &n_written); // min-installed-maps
00229         write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 1, &n_written); // max-installed-maps
00230         write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 34, &n_written); // root-visual
00231         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); // backing-stores
00232         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); // save-unders
00233         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 24, &n_written); // root-depth
00234         n_depths_offset = n_written;
00235         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written);
00236 
00237         depth = 0;
00238         while (TRUE)
00239         {
00240             GList *visual_link;
00241             guint16 n_visuals = 0;
00242 
00243             /* Find the next depth to this one */
00244             guint8 next_depth = 255;
00245             for (visual_link = screen->priv->visuals; visual_link; visual_link = visual_link->next)
00246             {
00247                 XVisual *visual = visual_link->data;
00248                 if (visual->priv->depth > depth && visual->priv->depth < next_depth)
00249                     next_depth = visual->priv->depth;
00250             }
00251             if (next_depth == 255)
00252                 break;
00253             depth = next_depth;
00254             n_depths++;
00255 
00256             for (visual_link = screen->priv->visuals; visual_link; visual_link = visual_link->next)
00257             {
00258                 XVisual *visual = visual_link->data;
00259                 if (visual->priv->depth == depth)
00260                     n_visuals++;
00261             }
00262 
00263             write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, depth, &n_written);
00264             write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written);
00265             write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, n_visuals, &n_written);
00266             write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 4, &n_written);
00267 
00268             for (visual_link = screen->priv->visuals; visual_link; visual_link = visual_link->next)
00269             {
00270                 XVisual *visual = visual_link->data;
00271 
00272                 if (visual->priv->depth != depth)
00273                     continue;
00274 
00275                 write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, visual->priv->id, &n_written);
00276                 write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, visual->priv->class, &n_written);
00277                 write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, visual->priv->bits_per_rgb_value, &n_written);
00278                 write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, visual->priv->colormap_entries, &n_written);
00279                 write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, visual->priv->red_mask, &n_written);
00280                 write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, visual->priv->green_mask, &n_written);
00281                 write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, visual->priv->blue_mask, &n_written);
00282                 write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 4, &n_written);
00283             }
00284         }
00285 
00286         write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, n_depths, &n_depths_offset);
00287     }
00288 
00289     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, (n_written - length_offset) / 4, &length_offset);
00290 
00291     send (g_io_channel_unix_get_fd (client->priv->channel), buffer, n_written, 0);
00292 }
00293 
00294 void
00295 x_client_send_error (XClient *client, int type, int major, int minor)
00296 {
00297     guint8 buffer[MAXIMUM_REQUEST_LENGTH];
00298     gsize n_written = 0;
00299 
00300     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, Error, &n_written);
00301     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, type, &n_written);
00302     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written);
00303     write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* resourceID */
00304     write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, minor, &n_written);
00305     write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, major, &n_written);
00306     write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 21, &n_written);
00307 
00308     send (g_io_channel_unix_get_fd (client->priv->channel), buffer, n_written, 0);
00309 }
00310 
00311 void
00312 x_client_disconnect (XClient *client)
00313 {
00314     g_io_channel_shutdown (client->priv->channel, TRUE, NULL);
00315 }
00316 
00317 static void
00318 x_client_init (XClient *client)
00319 {
00320     client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, x_client_get_type (), XClientPrivate);
00321     client->priv->sequence_number = 1;
00322 }
00323 
00324 static void
00325 x_client_class_init (XClientClass *klass)
00326 {
00327     g_type_class_add_private (klass, sizeof (XClientPrivate));
00328 
00329     x_client_signals[X_CLIENT_CONNECT] =
00330         g_signal_new ("connect",
00331                       G_TYPE_FROM_CLASS (klass),
00332                       G_SIGNAL_RUN_LAST,
00333                       G_STRUCT_OFFSET (XClientClass, connect),
00334                       NULL, NULL,
00335                       g_cclosure_marshal_VOID__POINTER,
00336                       G_TYPE_NONE, 1, G_TYPE_POINTER);
00337     x_client_signals[X_CLIENT_DISCONNECTED] =
00338         g_signal_new ("disconnected",
00339                       G_TYPE_FROM_CLASS (klass),
00340                       G_SIGNAL_RUN_LAST,
00341                       G_STRUCT_OFFSET (XClientClass, disconnected),
00342                       NULL, NULL,
00343                       g_cclosure_marshal_VOID__VOID,
00344                       G_TYPE_NONE, 0);
00345 }
00346 
00347 XServer *
00348 x_server_new (gint display_number)
00349 {
00350     XServer *server = g_object_new (x_server_get_type (), NULL);
00351     server->priv->display_number = display_number;
00352     server->priv->tcp_port = 6000 + display_number;
00353     return server;
00354 }
00355 
00356 XScreen *
00357 x_server_add_screen (XServer *server, guint32 white_pixel, guint32 black_pixel, guint32 current_input_masks, guint16 width_in_pixels, guint16 height_in_pixels, guint16 width_in_millimeters, guint16 height_in_millimeters)
00358 {
00359     XScreen *screen;
00360 
00361     screen = g_object_new (x_screen_get_type (), NULL);
00362 
00363     screen->priv->white_pixel = white_pixel;
00364     screen->priv->black_pixel = black_pixel;
00365     screen->priv->current_input_masks = current_input_masks;
00366     screen->priv->width_in_pixels = width_in_pixels;
00367     screen->priv->height_in_pixels = height_in_pixels;
00368     screen->priv->width_in_millimeters = width_in_millimeters;
00369     screen->priv->height_in_millimeters = height_in_millimeters;
00370   
00371     server->priv->screens = g_list_append (server->priv->screens, screen);
00372 
00373     return screen;
00374 }
00375 
00376 void
00377 x_server_add_pixmap_format (XServer *server, guint8 depth, guint8 bits_per_pixel, guint8 scanline_pad)
00378 {
00379     PixmapFormat *format;
00380   
00381     format = g_malloc0 (sizeof (PixmapFormat));
00382     format->depth = depth;
00383     format->bits_per_pixel = bits_per_pixel;
00384     format->scanline_pad = scanline_pad;
00385     server->priv->pixmap_formats = g_list_append (server->priv->pixmap_formats, format);
00386 }
00387 
00388 void
00389 x_server_set_listen_unix (XServer *server, gboolean listen_unix)
00390 {
00391     server->priv->listen_unix = listen_unix;
00392 }
00393 
00394 void
00395 x_server_set_listen_tcp (XServer *server, gboolean listen_tcp)
00396 {
00397     server->priv->listen_tcp = listen_tcp;
00398 }
00399 
00400 XVisual *
00401 x_screen_add_visual (XScreen *screen, guint8 depth, guint8 class, guint8 bits_per_rgb_value, guint16 colormap_entries, guint32 red_mask, guint32 green_mask, guint32 blue_mask)
00402 {
00403     XVisual *visual;
00404 
00405     visual = g_object_new (x_visual_get_type (), NULL);
00406     visual->priv->id = 0; // FIXME
00407     visual->priv->depth = depth;
00408     visual->priv->class = class;
00409     visual->priv->bits_per_rgb_value = bits_per_rgb_value;
00410     visual->priv->colormap_entries = colormap_entries;
00411     visual->priv->red_mask = red_mask;
00412     visual->priv->green_mask = green_mask;
00413     visual->priv->blue_mask = blue_mask;
00414     
00415     return visual;
00416 }
00417 
00418 static void
00419 decode_connection_request (XClient *client, const guint8 *buffer, gssize buffer_length)
00420 {
00421     guint8 byte_order;
00422     gsize offset = 0;
00423     guint16 n;
00424     XConnect *message;
00425 
00426     byte_order = read_card8 (buffer, buffer_length, &offset);
00427     if (!(byte_order == 'B' || byte_order == 'l'))
00428     {
00429         g_warning ("Invalid byte order");
00430         return;
00431     }
00432   
00433     message = g_malloc0 (sizeof (XConnect));
00434 
00435     message->byte_order = byte_order == 'B' ? X_BYTE_ORDER_MSB : X_BYTE_ORDER_LSB;
00436     read_padding (1, &offset);
00437     message->protocol_major_version = read_card16 (buffer, buffer_length, message->byte_order, &offset);
00438     message->protocol_minor_version = read_card16 (buffer, buffer_length, message->byte_order, &offset);
00439     n = read_card16 (buffer, buffer_length, message->byte_order, &offset);
00440     message->authorization_protocol_data_length = read_card16 (buffer, buffer_length, message->byte_order, &offset);
00441     read_padding (2, &offset);
00442     message->authorization_protocol_name = read_padded_string (buffer, buffer_length, n, &offset);
00443     message->authorization_protocol_data = read_string8 (buffer, buffer_length, message->authorization_protocol_data_length, &offset);
00444     read_padding (pad (message->authorization_protocol_data_length), &offset);
00445 
00446     /* Store information about the client */
00447     client->priv->byte_order = message->byte_order;
00448     client->priv->connected = TRUE;
00449 
00450     g_signal_emit (client, x_client_signals[X_CLIENT_CONNECT], 0, message);
00451 
00452     g_free (message->authorization_protocol_name);
00453     g_free (message->authorization_protocol_data);
00454     g_free (message);
00455 }
00456 
00457 static void
00458 process_intern_atom (XClient *client, const guint8 *buffer, gssize buffer_length)
00459 {
00460     /* Decode */
00461 
00462     gsize offset = 0;
00463     guint8 onlyIfExists;
00464     guint16 n;
00465     gchar *name;
00466     int atom;
00467 
00468     read_padding (1, &offset); /* reqType */
00469     onlyIfExists = read_card8 (buffer, buffer_length, &offset);
00470     read_padding (2, &offset); /* length */
00471     n = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
00472     read_padding (2, &offset);
00473     name = read_padded_string (buffer, buffer_length, n, &offset);
00474 
00475     /* Process */
00476 
00477     atom = client->priv->server->priv->next_atom_index++;
00478 
00479     if (onlyIfExists)
00480     {
00481         g_free (name);
00482         if (!g_hash_table_lookup (client->priv->server->priv->atoms, GINT_TO_POINTER (atom)))
00483         {
00484             x_client_send_error (client, BadAtom, InternAtom, 0);
00485             return;
00486         }
00487     }
00488     else
00489         g_hash_table_insert (client->priv->server->priv->atoms, GINT_TO_POINTER (atom), name);
00490 
00491     /* Reply */
00492 
00493     guint8 outBuffer[MAXIMUM_REQUEST_LENGTH];
00494     gsize n_written = 0;
00495 
00496     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written);
00497     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written);
00498     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written);
00499     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */
00500     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, atom, &n_written);
00501     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written);
00502 
00503     send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0);
00504 }
00505 
00506 static void
00507 process_get_property (XClient *client, const guint8 *buffer, gssize buffer_length)
00508 {
00509     /* Decode */
00510 
00511     gsize offset = 0;
00512     guint8 delete;
00513     guint32 property;
00514     guint32 type;
00515 
00516     read_padding (1, &offset); /* reqType */
00517     delete = read_card8 (buffer, buffer_length, &offset);
00518     read_padding (2, &offset); /* length */
00519     read_padding (4, &offset); /* window */
00520     property = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
00521     type = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
00522     read_padding (4, &offset); /* longOffset */
00523     read_padding (4, &offset); /* longLength */
00524 
00525     /* Process */
00526 
00527     gchar *name = g_hash_table_lookup (client->priv->server->priv->atoms, GINT_TO_POINTER (property));
00528     GString *reply = NULL;
00529     guint8 format = 8;
00530 
00531     if (g_strcmp0 (name, "_XKB_RULES_NAMES") == 0)
00532     {
00533         GKeyFile *config;
00534 
00535         config = g_key_file_new ();
00536         g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
00537 
00538         reply = g_string_new ("");
00539 
00540         g_string_append (reply, "evdev"); /* rules file */
00541         g_string_append_c (reply, 0); /* embedded null byte */
00542 
00543         g_string_append (reply, "pc105"); /* model name */
00544         g_string_append_c (reply, 0); /* embedded null byte */
00545 
00546         if (g_key_file_has_key (config, "test-xserver-config", "keyboard-layout", NULL))
00547             g_string_append (reply, g_key_file_get_string (config, "test-xserver-config", "keyboard-layout", NULL));
00548         else
00549             g_string_append (reply, "us");
00550         g_string_append_c (reply, 0); /* embedded null byte */
00551 
00552         if (g_key_file_has_key (config, "test-xserver-config", "keyboard-variant", NULL))
00553             g_string_append (reply, g_key_file_get_string (config, "test-xserver-config", "keyboard-variant", NULL));
00554         g_string_append_c (reply, 0); /* embedded null byte */
00555 
00556         /* no xkb options */
00557         g_string_append_c (reply, 0); /* embedded null byte */
00558 
00559         g_key_file_free (config);
00560     }
00561 
00562     if (name && delete)
00563         g_hash_table_remove (client->priv->server->priv->atoms, GINT_TO_POINTER (property));
00564 
00565     /* Reply */
00566 
00567     if (!reply)
00568     {
00569         x_client_send_error (client, BadImplementation, GetProperty, 0);
00570         return;
00571     }
00572 
00573     guint8 outBuffer[MAXIMUM_REQUEST_LENGTH];
00574     gsize n_written = 0, length_offset, packet_start;
00575 
00576     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written);
00577     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, format, &n_written);
00578     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written);
00579     length_offset = n_written;
00580     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */
00581     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, type, &n_written);
00582     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* bytesAfter */
00583     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, reply->len, &n_written);
00584     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 12, &n_written);
00585     packet_start = n_written;
00586 
00587     write_string8 (outBuffer, MAXIMUM_REQUEST_LENGTH, (guint8 *) reply->str, reply->len, &n_written);
00588     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, pad (reply->len), &n_written);
00589 
00590     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, (n_written - packet_start) / 4, &length_offset);
00591 
00592     send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0);
00593 
00594     /* Cleanup */
00595 
00596     g_string_free (reply, TRUE);
00597 }
00598 
00599 static void
00600 process_query_extension (XClient *client, const guint8 *buffer, gssize buffer_length)
00601 {
00602     /* Decode */
00603 
00604     gsize offset = 0;
00605     guint8 n;
00606     gchar *name;
00607 
00608     read_padding (1, &offset); /* reqType */
00609     read_padding (1, &offset); /* pad */
00610     read_padding (2, &offset); /* length */
00611     n = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
00612     read_padding (2, &offset); /* pad */
00613     name = read_padded_string (buffer, buffer_length, n, &offset);
00614 
00615     /* Process */
00616 
00617     guint8 present = 0;
00618     if (g_strcmp0 (name, "XKEYBOARD") == 0)
00619         present = 1;
00620 
00621     /* Reply */
00622 
00623     guint8 outBuffer[MAXIMUM_REQUEST_LENGTH];
00624     gsize n_written = 0;
00625 
00626     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written);
00627     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written);
00628     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written);
00629     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */
00630     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, present, &n_written);
00631     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, kbUseExtension, &n_written); /* major_opcode */
00632     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); /* first_event */
00633     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); /* first_error */
00634     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written);
00635 
00636     send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0);
00637 
00638     /* Cleanup */
00639 
00640     g_free (name);
00641 }
00642 
00643 static void
00644 process_kb_use_extension (XClient *client, const guint8 *buffer, gssize buffer_length)
00645 {
00646     /* Nothing to decode, we don't care about parameters */
00647 
00648     /* Reply */
00649 
00650     guint8 outBuffer[MAXIMUM_REQUEST_LENGTH];
00651     gsize n_written = 0;
00652 
00653     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written);
00654     write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written); /* supported */
00655     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written);
00656     write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */
00657     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 1, &n_written); /* serverMajor */
00658     write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* serverMinor */
00659     write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written);
00660 
00661     send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0);
00662 }
00663 
00664 static void
00665 decode_request (XClient *client, const guint8 *buffer, gssize buffer_length)
00666 {
00667     int opcode;
00668     gsize offset = 0;
00669 
00670     while (offset < buffer_length)
00671     {
00672         gsize start_offset;
00673         guint16 length;
00674 
00675         start_offset = offset;
00676         opcode = read_card8 (buffer, buffer_length, &offset);
00677         read_card8 (buffer, buffer_length, &offset);
00678         length = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset) * 4;
00679 
00680         g_debug ("Got opcode=%d length=%d", opcode, length);
00681         offset = start_offset + length;
00682 
00683         switch (opcode)
00684         {
00685         case InternAtom:
00686             process_intern_atom (client, buffer + start_offset, length);
00687             break;
00688         case GetProperty:
00689             process_get_property (client, buffer + start_offset, length);
00690             break;
00691         case QueryExtension:
00692             process_query_extension (client, buffer + start_offset, length);
00693             break;
00694         case kbUseExtension:
00695             process_kb_use_extension (client, buffer + start_offset, length);
00696             break;
00697         default:
00698             /* Send an error because we don't understand the opcode yet */
00699             x_client_send_error (client, BadImplementation, opcode, 0);
00700             break;
00701         }
00702 
00703         client->priv->sequence_number++;
00704     }
00705 }
00706 
00707 static gboolean
00708 socket_data_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
00709 {
00710     XClient *client = data;
00711     guint8 buffer[MAXIMUM_REQUEST_LENGTH];
00712     gssize n_read;
00713 
00714     n_read = recv (g_io_channel_unix_get_fd (channel), buffer, MAXIMUM_REQUEST_LENGTH, 0);
00715     if (n_read < 0)
00716         g_warning ("Error reading from socket: %s", strerror (errno));
00717     else if (n_read == 0)
00718     {
00719         g_signal_emit (client, x_client_signals[X_CLIENT_DISCONNECTED], 0);
00720         return FALSE;
00721     }
00722     else
00723     {
00724         if (client->priv->connected)
00725             decode_request (client, buffer, n_read);
00726         else
00727             decode_connection_request (client, buffer, n_read);
00728     }
00729 
00730     return TRUE;
00731 }
00732 
00733 static void
00734 x_client_disconnected_cb (XClient *client, XServer *server)
00735 {
00736     g_signal_handlers_disconnect_matched (client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, server);
00737     g_hash_table_remove (server->priv->clients, client->priv->channel);
00738     g_signal_emit (server, x_server_signals[X_SERVER_CLIENT_DISCONNECTED], 0, client);
00739 }
00740 
00741 static gboolean
00742 socket_connect_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
00743 {
00744     XServer *server = data;
00745     GSocket *data_socket;
00746     XClient *client;
00747     GError *error = NULL;
00748 
00749     if (channel == server->priv->unix_channel)
00750         data_socket = g_socket_accept (server->priv->unix_socket, NULL, &error);
00751     else
00752         data_socket = g_socket_accept (server->priv->tcp_socket, NULL, &error);
00753     if (error)
00754         g_warning ("Error accepting connection: %s", strerror (errno));
00755     g_clear_error (&error);
00756     if (!data_socket)
00757         return FALSE;
00758 
00759     client = g_object_new (x_client_get_type (), NULL);
00760     client->priv->server = server;
00761     g_signal_connect (client, "disconnected", G_CALLBACK (x_client_disconnected_cb), server);
00762     client->priv->socket = data_socket;
00763     client->priv->channel = g_io_channel_unix_new (g_socket_get_fd (data_socket));
00764     g_hash_table_insert (server->priv->clients, client->priv->channel, client);
00765     g_io_add_watch (client->priv->channel, G_IO_IN, socket_data_cb, client);
00766 
00767     g_signal_emit (server, x_server_signals[X_SERVER_CLIENT_CONNECTED], 0, client);
00768 
00769     return TRUE;
00770 }
00771 
00772 gboolean
00773 x_server_start (XServer *server)
00774 {
00775     if (server->priv->listen_unix)
00776     {
00777         GError *error = NULL;
00778       
00779         server->priv->socket_path = g_strdup_printf ("/tmp/.X11-unix/X%d", server->priv->display_number);
00780 
00781         server->priv->unix_socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
00782         if (!server->priv->unix_socket ||
00783             !g_socket_bind (server->priv->unix_socket, g_unix_socket_address_new (server->priv->socket_path), TRUE, &error) ||
00784             !g_socket_listen (server->priv->unix_socket, &error))
00785         {
00786             g_warning ("Error creating Unix X socket: %s", error->message);
00787             return FALSE;
00788         }
00789         server->priv->unix_channel = g_io_channel_unix_new (g_socket_get_fd (server->priv->unix_socket));
00790         g_io_add_watch (server->priv->unix_channel, G_IO_IN, socket_connect_cb, server);
00791     }
00792 
00793     if (server->priv->listen_tcp)
00794     {
00795         GError *error = NULL;
00796 
00797         server->priv->tcp_socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &error);
00798         if (!server->priv->tcp_socket ||
00799             !g_socket_bind (server->priv->tcp_socket, g_inet_socket_address_new (g_inet_address_new_any (G_SOCKET_FAMILY_IPV4), server->priv->tcp_port), TRUE, &error) ||
00800             !g_socket_listen (server->priv->tcp_socket, &error))
00801         {
00802             g_warning ("Error creating TCP/IP X socket: %s", error->message);
00803             return FALSE;
00804         }
00805         server->priv->tcp_channel = g_io_channel_unix_new (g_socket_get_fd (server->priv->tcp_socket));
00806         g_io_add_watch (server->priv->tcp_channel, G_IO_IN, socket_connect_cb, server);
00807     }
00808 
00809     return TRUE;
00810 }
00811 
00812 gsize
00813 x_server_get_n_clients (XServer *server)
00814 {
00815     return g_hash_table_size (server->priv->clients);
00816 }
00817 
00818 static void
00819 x_server_init (XServer *server)
00820 {
00821     server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, x_server_get_type (), XServerPrivate);
00822     server->priv->vendor = g_strdup ("");
00823     server->priv->min_keycode = 8;
00824     server->priv->min_keycode = 255;
00825     server->priv->screens = NULL;
00826     server->priv->listen_unix = TRUE;
00827     server->priv->listen_tcp = TRUE;
00828     server->priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) g_io_channel_unref, g_object_unref);
00829     server->priv->atoms = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
00830     server->priv->next_atom_index = 1;
00831     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("PRIMARY"));
00832     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("SECONDARY"));
00833     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("ARC"));
00834     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("ATOM"));
00835     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("BITMAP"));
00836     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CARDINAL"));
00837     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("COLORMAP"));
00838     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CURSOR"));
00839     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER0"));
00840     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER1"));
00841     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER2"));
00842     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER3"));
00843     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER4"));
00844     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER5"));
00845     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER6"));
00846     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CUT_BUFFER7"));
00847     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("DRAWABLE"));
00848     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("FONT"));
00849     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("INTEGER"));
00850     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("PIXMAP"));
00851     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("POINT"));
00852     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RECTANGLE"));
00853     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RESOURCE_MANAGER"));
00854     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_COLOR_MAP"));
00855     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_BEST_MAP"));
00856     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_BLUE_MAP"));
00857     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_DEFAULT_MAP"));
00858     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_GRAY_MAP"));
00859     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_GREEN_MAP"));
00860     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RGB_RED_MAP"));
00861     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("STRING"));
00862     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("VISUALID"));
00863     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WINDOW"));
00864     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_COMMAND"));
00865     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_HINTS"));
00866     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_CLIENT_MACHINE"));
00867     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_ICON_NAME"));
00868     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_ICON_SIZE"));
00869     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_NAME"));
00870     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_NORMAL_HINTS"));
00871     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_SIZE_HINTS"));
00872     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_ZOOM_HINTS"));
00873     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("MIN_SPACE"));
00874     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("NORM_SPACE"));
00875     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("MAX_SPACE"));
00876     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("END_SPACE"));
00877     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("SUPERSCRIPT_X"));
00878     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("SUPERSCRIPT_Y"));
00879     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("SUBSCRIPT_X"));
00880     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("SUBSCRIPT_Y"));
00881     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("UNDERLINE_POSITION"));
00882     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("UNDERLINE_THICKNESS"));
00883     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("STRIKEOUT_ASCENT"));
00884     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("STRIKEOUT_DESCENT"));
00885     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("ITALIC_ANGLE"));
00886     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("X_HEIGHT"));
00887     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("QUAD_WIDTH"));
00888     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WEIGHT"));
00889     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("POINT_SIZE"));
00890     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("RESOLUTION"));
00891     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("COPYRIGHT"));
00892     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("NOTICE"));
00893     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("FONT_NAME"));
00894     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("FAMILY_NAME"));
00895     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("FULL_NAME"));
00896     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("CAP_HEIGHT"));
00897     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_CLASS"));
00898     g_hash_table_insert (server->priv->atoms, GINT_TO_POINTER (server->priv->next_atom_index++), g_strdup ("WM_TRANSIENT_FOR"));
00899 }
00900 
00901 static void
00902 x_server_finalize (GObject *object)
00903 {
00904     XServer *server = (XServer *) object;
00905     g_free (server->priv->vendor);
00906     if (server->priv->socket_path)
00907         unlink (server->priv->socket_path);
00908     g_hash_table_unref (server->priv->atoms);
00909     G_OBJECT_CLASS (x_server_parent_class)->finalize (object);
00910 }
00911 
00912 static void
00913 x_server_class_init (XServerClass *klass)
00914 {
00915     GObjectClass *object_class = G_OBJECT_CLASS (klass);
00916     object_class->finalize = x_server_finalize;
00917     g_type_class_add_private (klass, sizeof (XServerPrivate));
00918     x_server_signals[X_SERVER_CLIENT_CONNECTED] =
00919         g_signal_new ("client-connected",
00920                       G_TYPE_FROM_CLASS (klass),
00921                       G_SIGNAL_RUN_LAST,
00922                       G_STRUCT_OFFSET (XServerClass, client_connected),
00923                       NULL, NULL,
00924                       g_cclosure_marshal_VOID__OBJECT,
00925                       G_TYPE_NONE, 1, x_client_get_type ());
00926     x_server_signals[X_SERVER_CLIENT_DISCONNECTED] =
00927         g_signal_new ("client-disconnected",
00928                       G_TYPE_FROM_CLASS (klass),
00929                       G_SIGNAL_RUN_LAST,
00930                       G_STRUCT_OFFSET (XServerClass, client_disconnected),
00931                       NULL, NULL,
00932                       g_cclosure_marshal_VOID__OBJECT,
00933                       G_TYPE_NONE, 1, x_client_get_type ());
00934 }
00935 
00936 static void
00937 x_screen_init (XScreen *screen)
00938 {
00939     screen->priv = G_TYPE_INSTANCE_GET_PRIVATE (screen, x_screen_get_type (), XScreenPrivate);
00940 }
00941 
00942 static void
00943 x_screen_class_init (XScreenClass *klass)
00944 {
00945     g_type_class_add_private (klass, sizeof (XScreenPrivate));
00946 }
00947 
00948 static void
00949 x_visual_init (XVisual *visual)
00950 {
00951     visual->priv = G_TYPE_INSTANCE_GET_PRIVATE (visual, x_visual_get_type (), XVisualPrivate);
00952 }
00953 
00954 static void
00955 x_visual_class_init (XVisualClass *klass)
00956 {
00957     g_type_class_add_private (klass, sizeof (XVisualPrivate));
00958 }