gdk.c 12.3 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 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
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
28 29

#include <string.h>
30
#include <stdlib.h>
Elliot Lee's avatar
Elliot Lee committed
31

Owen Taylor's avatar
Started  
Owen Taylor committed
32
#include "gdk.h"
33
#include "gdkinternals.h"
Elliot Lee's avatar
Elliot Lee committed
34

35 36 37 38
#ifndef HAVE_XCONVERTCASE
#include "gdkkeysyms.h"
#endif

Elliot Lee's avatar
Elliot Lee committed
39 40 41 42 43 44 45 46 47 48
typedef struct _GdkPredicate  GdkPredicate;

struct _GdkPredicate
{
  GdkEventFunc func;
  gpointer data;
};

/* Private variable declarations
 */
49
static int gdk_initialized = 0;			    /* 1 if the library is initialized,
Elliot Lee's avatar
Elliot Lee committed
50 51 52
						     * 0 otherwise.
						     */

53
static gchar  *gdk_progclass = NULL;
54 55
static gint    gdk_argc = 0;
static gchar **gdk_argv = NULL;
56

57
#ifdef G_ENABLE_DEBUG
58
static const GDebugKey gdk_debug_keys[] = {
59 60 61
  {"events",	    GDK_DEBUG_EVENTS},
  {"misc",	    GDK_DEBUG_MISC},
  {"dnd",	    GDK_DEBUG_DND},
Jacob Berkman's avatar
Jacob Berkman committed
62 63
  {"xim",	    GDK_DEBUG_XIM},
  {"nograbs",       GDK_DEBUG_NOGRABS},
64 65 66 67 68 69 70
  {"colormap",	    GDK_DEBUG_COLORMAP},
  {"gdkrgb",	    GDK_DEBUG_GDKRGB},
  {"gc",	    GDK_DEBUG_GC},
  {"pixmap",	    GDK_DEBUG_PIXMAP},
  {"image",	    GDK_DEBUG_IMAGE},
  {"input",	    GDK_DEBUG_INPUT},
  {"cursor",	    GDK_DEBUG_CURSOR},
71
  {"multihead",	    GDK_DEBUG_MULTIHEAD},
72
  {"xinerama",	    GDK_DEBUG_XINERAMA}
73
};
74

75
static const int gdk_ndebug_keys = G_N_ELEMENTS (gdk_debug_keys);
76

77
#endif /* G_ENABLE_DEBUG */
Elliot Lee's avatar
Elliot Lee committed
78

79
static GdkArgContext *
80 81 82 83 84 85 86 87 88
gdk_arg_context_new (gpointer cb_data)
{
  GdkArgContext *result = g_new (GdkArgContext, 1);
  result->tables = g_ptr_array_new ();
  result->cb_data = cb_data;

  return result;
}

89
static void
90 91 92 93 94 95
gdk_arg_context_destroy (GdkArgContext *context)
{
  g_ptr_array_free (context->tables, TRUE);
  g_free (context);
}

96
static void
97 98 99 100 101
gdk_arg_context_add_table (GdkArgContext *context, GdkArgDesc *table)
{
  g_ptr_array_add (context->tables, table);
}

102
static void
103 104 105 106 107 108 109 110 111 112
gdk_arg_context_parse (GdkArgContext *context, gint *argc, gchar ***argv)
{
  int i, j, k;

  if (argc && argv)
    {
      for (i = 1; i < *argc; i++)
	{
	  char *arg;
	  
113
	  if (!((*argv)[i][0] == '-' && (*argv)[i][1] == '-'))
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	    continue;
	  
	  arg = (*argv)[i] + 2;

	  /* '--' terminates list of arguments */
	  if (arg == 0)
	    {
	      (*argv)[i] = NULL;
	      break;
	    }
	      
	  for (j = 0; j < context->tables->len; j++)
	    {
	      GdkArgDesc *table = context->tables->pdata[j];
	      for (k = 0; table[k].name; k++)
		{
		  switch (table[k].type)
		    {
		    case GDK_ARG_STRING:
		    case GDK_ARG_CALLBACK:
		    case GDK_ARG_INT:
		      {
			int len = strlen (table[k].name);
			
			if (strncmp (arg, table[k].name, len) == 0 &&
139
			    (arg[len] == '=' || arg[len] == 0))
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
			  {
			    char *value = NULL;

			    (*argv)[i] = NULL;

			    if (arg[len] == '=')
			      value = arg + len + 1;
			    else if (i < *argc - 1)
			      {
				value = (*argv)[i + 1];
				(*argv)[i+1] = NULL;
				i++;
			      }
			    else
			      value = "";

			    switch (table[k].type)
			      {
			      case GDK_ARG_STRING:
				*(gchar **)table[k].location = g_strdup (value);
				break;
			      case GDK_ARG_INT:
				*(gint *)table[k].location = atoi (value);
				break;
			      case GDK_ARG_CALLBACK:
				(*table[k].callback)(table[k].name, value, context->cb_data);
				break;
			      default:
168
				;
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
			      }

			    goto next_arg;
			  }
			break;
		      }
		    case GDK_ARG_BOOL:
		    case GDK_ARG_NOBOOL:
		      if (strcmp (arg, table[k].name) == 0)
			{
			  (*argv)[i] = NULL;
			  
			  *(gboolean *)table[k].location = (table[k].type == GDK_ARG_BOOL) ? TRUE : FALSE;
			  goto next_arg;
			}
		    }
		}
	    }
	next_arg:
188
	  ;
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
	}
	  
      for (i = 1; i < *argc; i++)
	{
	  for (k = i; k < *argc; k++)
	    if ((*argv)[k] != NULL)
	      break;
	  
	  if (k > i)
	    {
	      k -= i;
	      for (j = i + k; j < *argc; j++)
		(*argv)[j-k] = (*argv)[j];
	      *argc -= k;
	    }
	}
    }
}

208
#ifdef G_ENABLE_DEBUG
209 210 211
static void
gdk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
{
212 213 214
  _gdk_debug_flags |= g_parse_debug_string (value,
					    (GDebugKey *) gdk_debug_keys,
					    gdk_ndebug_keys);
215 216 217 218 219
}

static void
gdk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
{
220 221 222
  _gdk_debug_flags &= ~g_parse_debug_string (value,
					     (GDebugKey *) gdk_debug_keys,
					     gdk_ndebug_keys);
223
}
224
#endif /* G_ENABLE_DEBUG */
225

226 227 228 229 230 231
static void
gdk_arg_class_cb (const char *key, const char *value, gpointer user_data)
{
  gdk_set_program_class (value);
}

232 233 234 235 236 237 238
static void
gdk_arg_name_cb (const char *key, const char *value, gpointer user_data)
{
  g_set_prgname (value);
}

static GdkArgDesc gdk_args[] = {
239 240 241
  { "class" ,       GDK_ARG_CALLBACK, NULL, gdk_arg_class_cb                   },
  { "name",         GDK_ARG_CALLBACK, NULL, gdk_arg_name_cb                    },
  { "display",      GDK_ARG_STRING,   &_gdk_display_name,     (GdkArgFunc)NULL },
242
  { "screen",       GDK_ARG_INT,      &_gdk_screen_number,    (GdkArgFunc)NULL },
243

244 245 246 247 248 249 250
#ifdef G_ENABLE_DEBUG
  { "gdk-debug",    GDK_ARG_CALLBACK, NULL, gdk_arg_debug_cb    },
  { "gdk-no-debug", GDK_ARG_CALLBACK, NULL, gdk_arg_no_debug_cb },
#endif /* G_ENABLE_DEBUG */
  { NULL }
};

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

/**
 * _gdk_get_command_line_args:
 * @argv: location to store argv pointer
 * @argc: location 
 * 
 * Retrieve the command line arguments passed to gdk_init().
 * The returned argv pointer points to static storage ; no
 * copy is made.
 **/
void
_gdk_get_command_line_args (int    *argc,
			    char ***argv)
{
  *argc = gdk_argc;
  *argv = gdk_argv;
}

/**
 * gdk_parse_args:
 * @argc: the number of command line arguments.
 * @argv: the array of command line arguments.
 * 
 * Parse command line arguments, and store for future
Owen Taylor's avatar
Owen Taylor committed
275
 * use by calls to gdk_display_open().
Elliot Lee's avatar
Elliot Lee committed
276
 *
277 278
 * Any arguments used by GDK are removed from the array and @argc and @argv are
 * updated accordingly.
Elliot Lee's avatar
Elliot Lee committed
279
 *
280 281
 * You shouldn't call this function explicitely if you are using
 * gtk_init(), gtk_init_check(), gdk_init(), or gdk_init_check().
Matthias Clasen's avatar
Matthias Clasen committed
282 283
 *
 * Since: 2.2
284 285 286
 **/
void
gdk_parse_args (int    *argc,
287
		char ***argv)
Elliot Lee's avatar
Elliot Lee committed
288
{
289
  GdkArgContext *arg_context;
290
  gint i;
291

292
  if (gdk_initialized)
293
    return;
294 295 296

  gdk_initialized = TRUE;

297
  /* Save a copy of the original argc and argv */
298 299
  if (argc && argv)
    {
300
      gdk_argc = *argc;
301
      
302 303 304 305
      gdk_argv = g_malloc ((gdk_argc + 1) * sizeof (char*));
      for (i = 0; i < gdk_argc; i++)
	gdk_argv[i] = g_strdup ((*argv)[i]);
      gdk_argv[gdk_argc] = NULL;
306
    }
307

308 309 310 311 312 313 314 315 316
  if (argc && argv && *argc > 0)
    {
      gchar *d;
      
      d = strrchr((*argv)[0], G_DIR_SEPARATOR);
      if (d != NULL)
	g_set_prgname (d + 1);
      else
	g_set_prgname ((*argv)[0]);
Elliot Lee's avatar
Elliot Lee committed
317
    }
318 319 320 321
  else
    {
      g_set_prgname ("<unknown>");
    }
322

323 324 325 326 327
  /* We set the fallback program class here, rather than lazily in
   * gdk_get_program_class, since we don't want -name to override it.
   */
  gdk_progclass = g_strdup (g_get_prgname ());
  if (gdk_progclass[0])
328
    gdk_progclass[0] = g_ascii_toupper (gdk_progclass[0]);
329
  
330 331 332 333
#ifdef G_ENABLE_DEBUG
  {
    gchar *debug_string = getenv("GDK_DEBUG");
    if (debug_string != NULL)
334
      _gdk_debug_flags = g_parse_debug_string (debug_string,
335 336 337 338
					      (GDebugKey *) gdk_debug_keys,
					      gdk_ndebug_keys);
  }
#endif	/* G_ENABLE_DEBUG */
339
  
340 341 342 343 344
  arg_context = gdk_arg_context_new (NULL);
  gdk_arg_context_add_table (arg_context, gdk_args);
  gdk_arg_context_add_table (arg_context, _gdk_windowing_args);
  gdk_arg_context_parse (arg_context, argc, argv);
  gdk_arg_context_destroy (arg_context);
345
  
346 347
  GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));

Owen Taylor's avatar
Owen Taylor committed
348
  g_type_init ();
349

350 351
  /* Do any setup particular to the windowing system
   */
352
  _gdk_windowing_init (argc, argv);
353
}
354

355 356 357 358 359 360 361
/** 
 * gdk_get_display_arg_name:
 *
 * Gets the display name specified in the command line arguments passed
 * to gdk_init() or gdk_parse_args(), if any.
 *
 * Returns: the display name, if specified explicitely, otherwise %NULL
362
 *   this string is owned by GTK+ and must not be modified or freed.
Matthias Clasen's avatar
Matthias Clasen committed
363 364
 *
 * Since: 2.2
365
 */
366
G_CONST_RETURN gchar *
367 368
gdk_get_display_arg_name (void)
{
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
  if (!_gdk_display_arg_name)
    {
      if (_gdk_screen_number >= 0)
	_gdk_display_arg_name = _gdk_windowing_substitute_screen_number (_gdk_display_name, _gdk_screen_number);
      else
	_gdk_display_arg_name = g_strdup (_gdk_display_name);
   }

   return _gdk_display_arg_name;
}

/**
 * gdk_display_open_default_libgtk_only:
 * 
 * Opens the default display specified by command line arguments or
 * environment variables, sets it as the default display, and returns
 * it.  gdk_parse_args must have been called first. If the default
 * display has previously been set, simply returns that. An internal
 * function that should not be used by applications.
 * 
 * Return value: the default display, if it could be opened,
 *   otherwise %NULL.
 **/
GdkDisplay *
gdk_display_open_default_libgtk_only (void)
{
  GdkDisplay *display;

397
  g_return_val_if_fail (gdk_initialized, NULL);
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
  
  display = gdk_display_get_default ();
  if (display)
    return display;

  display = gdk_display_open (gdk_get_display_arg_name ());

  if (!display && _gdk_screen_number >= 0)
    {
      g_free (_gdk_display_arg_name);
      _gdk_display_arg_name = g_strdup (_gdk_display_name);
      
      display = gdk_display_open (_gdk_display_name);
    }
  
  if (display)
    gdk_display_manager_set_default_display (gdk_display_manager_get (),
					     display);
  
  return display;
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
}

/*
 *--------------------------------------------------------------
 * gdk_init_check
 *
 *   Initialize the library for use.
 *
 * Arguments:
 *   "argc" is the number of arguments.
 *   "argv" is an array of strings.
 *
 * Results:
 *   "argc" and "argv" are modified to reflect any arguments
 *   which were not handled. (Such arguments should either
 *   be handled by the application or dismissed). If initialization
 *   fails, returns FALSE, otherwise TRUE.
 *
 * Side effects:
 *   The library is initialized.
 *
 *--------------------------------------------------------------
 */

gboolean
gdk_init_check (int    *argc,
		char ***argv)
{
  gdk_parse_args (argc, argv);
447

448
  return gdk_display_open_default_libgtk_only () != NULL;
449 450 451 452 453 454 455
}

void
gdk_init (int *argc, char ***argv)
{
  if (!gdk_init_check (argc, argv))
    {
456
      g_warning ("cannot open display: %s", gdk_get_display_arg_name ());
457 458
      exit(1);
    }
Elliot Lee's avatar
Elliot Lee committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
}

/*
 *--------------------------------------------------------------
 * gdk_exit
 *
 *   Restores the library to an un-itialized state and exits
 *   the program using the "exit" system call.
 *
 * Arguments:
 *   "errorcode" is the error value to pass to "exit".
 *
 * Results:
 *   Allocated structures are freed and the program exits
 *   cleanly.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

void
Tor Lillqvist's avatar
Tor Lillqvist committed
481
gdk_exit (gint errorcode)
Elliot Lee's avatar
Elliot Lee committed
482
{
483
  exit (errorcode);
Elliot Lee's avatar
Elliot Lee committed
484 485
}

486 487 488 489 490 491 492 493 494 495 496 497
void
gdk_threads_enter ()
{
  GDK_THREADS_ENTER ();
}

void
gdk_threads_leave ()
{
  GDK_THREADS_LEAVE ();
}

498 499 500 501 502
/**
 * gdk_threads_init:
 * 
 * Initializes GDK so that it can be used from multiple threads
 * in conjunction with gdk_threads_enter() and gdk_threads_leave().
503
 * g_thread_init() must be called previous to this function.
504 505 506 507 508 509 510 511
 *
 * This call must be made before any use of the main loop from
 * GTK+; to be safe, call it before gtk_init().
 **/
void
gdk_threads_init ()
{
  if (!g_thread_supported ())
512
    g_error ("g_thread_init() must be called before gdk_threads_init()");
513 514 515 516

  gdk_threads_mutex = g_mutex_new ();
}

517 518 519 520 521 522 523 524 525 526 527 528 529 530
G_CONST_RETURN char *
gdk_get_program_class (void)
{
  return gdk_progclass;
}

void
gdk_set_program_class (const char *program_class)
{
  if (gdk_progclass)
    g_free (gdk_progclass);

  gdk_progclass = g_strdup (program_class);
}