gdk.c 97.9 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10
/* 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
 * modify it under the terms of the GNU Library General Public
 * 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
Elliot Lee's avatar
Elliot Lee committed
12 13 14
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
20

Elliot Lee's avatar
Elliot Lee committed
21 22 23
/* If you don't want to use gdk's signal handlers define this */
/* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */

24
#include <X11/Xlocale.h>
Elliot Lee's avatar
Elliot Lee committed
25 26 27 28 29 30
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
31 32 33
#ifdef USE_XIM
#include <stdarg.h>
#endif
Elliot Lee's avatar
Elliot Lee committed
34 35 36 37 38 39 40 41 42 43 44

#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H_ */

#define XLIB_ILLEGAL_ACCESS
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xutil.h>
#include <X11/Xmu/WinUtil.h>
45 46 47
#ifdef USE_XIM
#include <X11/Xresource.h>
#endif
Elliot Lee's avatar
Elliot Lee committed
48 49 50 51
#include <X11/cursorfont.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinput.h"
52
#include "gdkx.h"
rodo's avatar
rodo committed
53
#include "gdkkeysyms.h"
54
#include "gdki18n.h"
Elliot Lee's avatar
Elliot Lee committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

#ifndef X_GETTIMEOFDAY
#define X_GETTIMEOFDAY(tv)  gettimeofday (tv, NULL)
#endif /* X_GETTIMEOFDAY */


#define DOUBLE_CLICK_TIME      250
#define TRIPLE_CLICK_TIME      500
#define DOUBLE_CLICK_DIST      5
#define TRIPLE_CLICK_DIST      5


#ifndef NO_FD_SET
#  define SELECT_MASK fd_set
#else
#  ifndef _AIX
71
typedef long fd_mask;
Elliot Lee's avatar
Elliot Lee committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#  endif
#  if defined(_IBMR2)
#    define SELECT_MASK void
#  else
#    define SELECT_MASK int
#  endif
#endif


typedef struct _GdkInput      GdkInput;
typedef struct _GdkPredicate  GdkPredicate;

struct _GdkInput
{
  gint tag;
  gint source;
  GdkInputCondition condition;
  GdkInputFunction function;
  gpointer data;
91
  GdkDestroyNotify destroy;
Elliot Lee's avatar
Elliot Lee committed
92 93 94 95 96 97 98 99 100 101 102
};

struct _GdkPredicate
{
  GdkEventFunc func;
  gpointer data;
};

/* 
 * Private function declarations
 */
103

104 105 106
static GdkEvent *gdk_event_new		(void);
static gint	 gdk_event_wait		(void);
static gint	 gdk_event_apply_filters (XEvent *xevent,
107 108
					  GdkEvent *event,
					  GList *filters);
109 110
static gint	 gdk_event_translate	(GdkEvent     *event, 
					 XEvent	      *xevent);
111
#if 0
112 113
static Bool	 gdk_event_get_type	(Display      *display, 
					 XEvent	      *xevent, 
Elliot Lee's avatar
Elliot Lee committed
114
					 XPointer      arg);
115
#endif
116 117
static void	 gdk_synthesize_click	(GdkEvent     *event, 
					 gint	       nclicks);
Elliot Lee's avatar
Elliot Lee committed
118

119
#ifndef HAVE_XCONVERTCASE
120 121 122
static void	 gdkx_XConvertCase	(KeySym	       symbol,
					 KeySym	      *lower,
					 KeySym	      *upper);
123 124 125
#define XConvertCase gdkx_XConvertCase
#endif

Elliot Lee's avatar
Elliot Lee committed
126 127 128
/* 
 * old junk from offix, we might use it though so leave it 
 */
129 130
Window	     gdk_get_client_window   (Display	  *dpy, 
				      Window	   win);
Elliot Lee's avatar
Elliot Lee committed
131
#ifdef WE_HAVE_MOTIF_DROPS_DONE
132
static GdkWindow *  gdk_drop_get_real_window	 (GdkWindow   *w, 
Elliot Lee's avatar
Elliot Lee committed
133 134
						  guint16     *x,
						  guint16     *y);
Elliot Lee's avatar
Elliot Lee committed
135
#endif
136 137
static void	    gdk_exit_func		 (void);
static int	    gdk_x_error			 (Display     *display, 
Elliot Lee's avatar
Elliot Lee committed
138
						  XErrorEvent *error);
139 140
static int	    gdk_x_io_error		 (Display     *display);
static RETSIGTYPE   gdk_signal			 (int	       signum);
Elliot Lee's avatar
Elliot Lee committed
141 142


143
#ifdef USE_XIM
144
static guint	     gdk_im_va_count	 (va_list list);
145
static XVaNestedList gdk_im_va_to_nested (va_list list, 
146
					  guint	  count);
147

148 149 150 151 152
static GdkIM  gdk_im_get		(void);
static gint   gdk_im_open		(XrmDatabase db,
					 gchar* res_name,
					 gchar* rec_class);
static void   gdk_im_close		(void);
153
static void   gdk_ic_cleanup		(void);
154

155 156
#endif /* USE_XIM */

157 158 159 160
GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
					 GdkEvent  *event,
					 gpointer   data);

Elliot Lee's avatar
Elliot Lee committed
161 162
/* Private variable declarations
 */
163
static int gdk_initialized = 0;			    /* 1 if the library is initialized,
Elliot Lee's avatar
Elliot Lee committed
164 165
						     * 0 otherwise.
						     */
166 167 168 169 170
static int connection_number = 0;		    /* The file descriptor number of our
						     *	connection to the X server. This
						     *	is used so that we may determine
						     *	when events are pending by using
						     *	the "select" system call.
Elliot Lee's avatar
Elliot Lee committed
171 172 173
						     */


174 175
static struct timeval start;			    /* The time at which the library was
						     *	last initialized.
Elliot Lee's avatar
Elliot Lee committed
176
						     */
177 178 179 180 181
static struct timeval timer;			    /* Timeout interval to use in the call
						     *	to "select". This is used in
						     *	conjunction with "timerp" to create
						     *	a maximum time to wait for an event
						     *	to arrive.
Elliot Lee's avatar
Elliot Lee committed
182
						     */
183 184 185 186
static struct timeval *timerp;			    /* The actual timer passed to "select"
						     *	This may be NULL, in which case
						     *	"select" will block until an event
						     *	arrives.
Elliot Lee's avatar
Elliot Lee committed
187
						     */
188 189
static guint32 timer_val;			    /* The timeout length as specified by
						     *	the user in milliseconds.
Elliot Lee's avatar
Elliot Lee committed
190
						     */
191 192 193 194 195 196 197
static GList *inputs;				    /* A list of the input file descriptors
						     *	that we care about. Each list node
						     *	contains a GdkInput struct that describes
						     *	when we are interested in the specified
						     *	file descriptor. That is, when it is
						     *	available for read, write or has an
						     *	exception pending.
Elliot Lee's avatar
Elliot Lee committed
198
						     */
199 200 201
static guint32 button_click_time[2];		    /* The last 2 button click times. Used
						     *	to determine if the latest button click
						     *	is part of a double or triple click.
Elliot Lee's avatar
Elliot Lee committed
202
						     */
203 204 205
static GdkWindow *button_window[2];		    /* The last 2 windows to receive button presses.
						     *	Also used to determine if the latest button
						     *	click is part of a double or triple click.
Elliot Lee's avatar
Elliot Lee committed
206
						     */
207
static guint button_number[2];			    /* The last 2 buttons to be pressed.
Elliot Lee's avatar
Elliot Lee committed
208
						     */
209
static GdkWindowPrivate *xgrab_window = NULL;	    /* Window that currently holds the
210
						     *	x pointer grab
211
						     */
Elliot Lee's avatar
Elliot Lee committed
212

213 214
static GList *client_filters;	                    /* Filters for client messages */

215 216 217 218 219 220 221 222 223 224 225
#ifdef USE_XIM
static gint xim_using;				/* using XIM Protocol if TRUE */
static GdkIM xim_im;				/* global IM */
static XIMStyles* xim_styles;			/* im supports these styles */
static XIMStyle xim_best_allowed_style;
static GdkICPrivate *xim_ic;			/* currently using IC */
static GdkWindow* xim_window;			/* currently using Widow */
static GList* xim_ic_list;

#endif

Elliot Lee's avatar
Elliot Lee committed
226 227 228 229 230
static GList *putback_events = NULL;

static gulong base_id;
static gint autorepeat;

231
#ifdef G_ENABLE_DEBUG
232
static const GDebugKey gdk_debug_keys[] = {
233 234 235
  {"events",	    GDK_DEBUG_EVENTS},
  {"misc",	    GDK_DEBUG_MISC},
  {"dnd",	    GDK_DEBUG_DND},
236
  {"color-context", GDK_DEBUG_COLOR_CONTEXT},
237
  {"xim",	    GDK_DEBUG_XIM}
238
};
239 240 241

static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);

242
#endif /* G_ENABLE_DEBUG */
Elliot Lee's avatar
Elliot Lee committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

/*
 *--------------------------------------------------------------
 * gdk_init
 *
 *   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).
 *
 * Side effects:
 *   The library is initialized.
 *
 *--------------------------------------------------------------
 */

void
266
gdk_init (int	 *argc,
Elliot Lee's avatar
Elliot Lee committed
267 268 269
	  char ***argv)
{
  XKeyboardState keyboard_state;
270 271
  gint synchronize;
  gint i, j, k;
Elliot Lee's avatar
Elliot Lee committed
272
  XClassHint *class_hint;
273 274
  gchar **argv_orig = NULL;
  gint argc_orig = 0;
275
  
276 277
  if (gdk_initialized)
    return;
278
  
279 280 281 282 283 284 285 286 287
  if (argc && argv)
    {
      argc_orig = *argc;
      
      argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
      for (i = 0; i < argc_orig; i++)
	argv_orig[i] = g_strdup ((*argv)[i]);
      argv_orig[argc_orig] = NULL;
    }
288
  
Elliot Lee's avatar
Elliot Lee committed
289
  X_GETTIMEOFDAY (&start);
290
  
Elliot Lee's avatar
Elliot Lee committed
291
#ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
Elliot Lee's avatar
Elliot Lee committed
292 293 294 295 296 297 298
  signal (SIGHUP, gdk_signal);
  signal (SIGINT, gdk_signal);
  signal (SIGQUIT, gdk_signal);
  signal (SIGBUS, gdk_signal);
  signal (SIGSEGV, gdk_signal);
  signal (SIGPIPE, gdk_signal);
  signal (SIGTERM, gdk_signal);
Elliot Lee's avatar
Elliot Lee committed
299
#endif
300
  
Elliot Lee's avatar
Elliot Lee committed
301
  gdk_display_name = NULL;
302
  
Elliot Lee's avatar
Elliot Lee committed
303 304
  XSetErrorHandler (gdk_x_error);
  XSetIOErrorHandler (gdk_x_io_error);
305
  
Elliot Lee's avatar
Elliot Lee committed
306
  synchronize = FALSE;
307
  
308 309 310 311 312 313 314 315 316
#ifdef G_ENABLE_DEBUG
  {
    gchar *debug_string = getenv("GDK_DEBUG");
    if (debug_string != NULL)
      gdk_debug_flags = g_parse_debug_string (debug_string,
					      gdk_debug_keys,
					      gdk_ndebug_keys);
  }
#endif	/* G_ENABLE_DEBUG */
317
  
Elliot Lee's avatar
Elliot Lee committed
318 319 320
  if (argc && argv)
    {
      if (*argc > 0)
321 322
	{
	  gchar *d;
323
	  
324 325
	  d = strrchr((*argv)[0],'/');
	  if (d != NULL)
326
	    g_set_prgname (d + 1);
327
	  else
328
	    g_set_prgname ((*argv)[0]);
329
	}
330
      
Elliot Lee's avatar
Elliot Lee committed
331 332
      for (i = 1; i < *argc;)
	{
333
#ifdef G_ENABLE_DEBUG	  
334 335
	  if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
	      (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
Elliot Lee's avatar
Elliot Lee committed
336
	    {
337 338 339 340 341 342 343 344 345
	      gchar *equal_pos = strchr ((*argv)[i], '=');
	      
	      if (equal_pos != NULL)
		{
		  gdk_debug_flags |= g_parse_debug_string (equal_pos+1,
							   gdk_debug_keys,
							   gdk_ndebug_keys);
		}
	      else if ((i + 1) < *argc && (*argv)[i + 1])
Elliot Lee's avatar
Elliot Lee committed
346
		{
347 348 349
		  gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
							   gdk_debug_keys,
							   gdk_ndebug_keys);
350
		  (*argv)[i] = NULL;
351 352
		  i += 1;
		}
353
	      (*argv)[i] = NULL;
354
	    }
355 356
	  else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
		   (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
357
	    {
358
	      gchar *equal_pos = strchr ((*argv)[i], '=');
359
	      
360 361 362 363 364 365 366
	      if (equal_pos != NULL)
		{
		  gdk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
							    gdk_debug_keys,
							    gdk_ndebug_keys);
		}
	      else if ((i + 1) < *argc && (*argv)[i + 1])
367 368 369 370
		{
		  gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
							    gdk_debug_keys,
							    gdk_ndebug_keys);
371
		  (*argv)[i] = NULL;
Elliot Lee's avatar
Elliot Lee committed
372 373
		  i += 1;
		}
374
	      (*argv)[i] = NULL;
Elliot Lee's avatar
Elliot Lee committed
375
	    }
Owen Taylor's avatar
Owen Taylor committed
376
	  else 
377
#endif /* G_ENABLE_DEBUG */
Owen Taylor's avatar
Owen Taylor committed
378
	    if (strcmp ("--display", (*argv)[i]) == 0)
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
	      {
		(*argv)[i] = NULL;
		
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    gdk_display_name = g_strdup ((*argv)[i + 1]);
		    (*argv)[i + 1] = NULL;
		    i += 1;
		  }
	      }
	    else if (strcmp ("--sync", (*argv)[i]) == 0)
	      {
		(*argv)[i] = NULL;
		synchronize = TRUE;
	      }
	    else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
	      {
		(*argv)[i] = NULL;
		gdk_use_xshm = FALSE;
	      }
	    else if (strcmp ("--name", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
404
		    g_set_prgname ((*argv)[i]);
405 406 407 408 409 410 411 412 413 414 415 416
		    (*argv)[i] = NULL;
		  }
	      }
	    else if (strcmp ("--class", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
		    gdk_progclass = (*argv)[i];
		    (*argv)[i] = NULL;
		  }
	      }
Elliot Lee's avatar
Elliot Lee committed
417
#ifdef XINPUT_GXI
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
	    else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
		    gdk_input_gxid_host = ((*argv)[i]);
		    (*argv)[i] = NULL;
		  }
	      }
	    else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
		    gdk_input_gxid_port = atoi ((*argv)[i]);
		    (*argv)[i] = NULL;
		  }
	      }
Elliot Lee's avatar
Elliot Lee committed
436
#endif
437
#ifdef USE_XIM
438 439 440 441 442 443
	    else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
		    if (strcmp ("none", (*argv)[i]) == 0)
444
		      gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
445
		    else if (strcmp ("nothing", (*argv)[i]) == 0)
446
		      gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
447
		    else if (strcmp ("area", (*argv)[i]) == 0)
448
		      gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
449
		    else if (strcmp ("position", (*argv)[i]) == 0)
450
		      gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
451
		    else if (strcmp ("callbacks", (*argv)[i]) == 0)
452
		      gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
453 454 455 456 457 458 459 460
		  }
	      }
	    else if (strcmp ("--xim-status", (*argv)[i]) == 0)
	      {
		if ((i + 1) < *argc && (*argv)[i + 1])
		  {
		    (*argv)[i++] = NULL;
		    if (strcmp ("none", (*argv)[i]) == 0)
461
		      gdk_im_set_best_style (GDK_IM_STATUS_NONE);
462
		    else if (strcmp ("nothing", (*argv)[i]) == 0)
463
		      gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
464
		    else if (strcmp ("area", (*argv)[i]) == 0)
465
		      gdk_im_set_best_style (GDK_IM_STATUS_AREA);
466
		    else if (strcmp ("callbacks", (*argv)[i]) == 0)
467
		      gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
468 469
		  }
	      }
470
#endif
471
	  
Elliot Lee's avatar
Elliot Lee committed
472 473
	  i += 1;
	}
474
      
Elliot Lee's avatar
Elliot Lee committed
475 476 477 478 479
      for (i = 1; i < *argc; i++)
	{
	  for (k = i; k < *argc; k++)
	    if ((*argv)[k] != NULL)
	      break;
480
	  
Elliot Lee's avatar
Elliot Lee committed
481 482 483 484 485 486 487 488 489 490 491
	  if (k > i)
	    {
	      k -= i;
	      for (j = i + k; j < *argc; j++)
		(*argv)[j-k] = (*argv)[j];
	      *argc -= k;
	    }
	}
    }
  else
    {
492
      g_set_prgname ("<unknown>");
Elliot Lee's avatar
Elliot Lee committed
493
    }
494
  
495
  GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
496
  
Elliot Lee's avatar
Elliot Lee committed
497 498
  gdk_display = XOpenDisplay (gdk_display_name);
  if (!gdk_display)
499 500 501 502
    {
      g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
      exit(1);
    }
503
  
Elliot Lee's avatar
Elliot Lee committed
504 505 506 507 508 509
  /* This is really crappy. We have to look into the display structure
   *  to find the base resource id. This is only needed for recording
   *  and playback of events.
   */
  /* base_id = RESOURCE_BASE; */
  base_id = 0;
510 511
  GDK_NOTE (EVENTS, g_message ("base id: %lu", base_id));
  
Elliot Lee's avatar
Elliot Lee committed
512
  connection_number = ConnectionNumber (gdk_display);
513
  GDK_NOTE (MISC,
514 515
	    g_message ("connection number: %d", connection_number));
  
Elliot Lee's avatar
Elliot Lee committed
516 517
  if (synchronize)
    XSynchronize (gdk_display, True);
518
  
Elliot Lee's avatar
Elliot Lee committed
519 520
  gdk_screen = DefaultScreen (gdk_display);
  gdk_root_window = RootWindow (gdk_display, gdk_screen);
521
  
Elliot Lee's avatar
Elliot Lee committed
522 523 524
  gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
					  10, 10, 10, 10, 0, 0 , 0);
  class_hint = XAllocClassHint();
525
  class_hint->res_name = g_get_prgname ();
526 527
  if (gdk_progclass == NULL)
    {
528
      gdk_progclass = g_strdup (g_get_prgname ());
529 530
      gdk_progclass[0] = toupper (gdk_progclass[0]);
    }
Elliot Lee's avatar
Elliot Lee committed
531 532 533 534
  class_hint->res_class = gdk_progclass;
  XSetClassHint(gdk_display, gdk_leader_window, class_hint);
  XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
  XFree (class_hint);
535 536 537 538 539
  
  for (i = 0; i < argc_orig; i++)
    g_free(argv_orig[i]);
  g_free(argv_orig);
  
Elliot Lee's avatar
Elliot Lee committed
540 541 542 543 544 545
  gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
  gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
  gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
  gdk_wm_window_protocols[0] = gdk_wm_delete_window;
  gdk_wm_window_protocols[1] = gdk_wm_take_focus;
  gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
546
  
Elliot Lee's avatar
Elliot Lee committed
547 548
  XGetKeyboardControl (gdk_display, &keyboard_state);
  autorepeat = keyboard_state.global_auto_repeat;
549
  
Elliot Lee's avatar
Elliot Lee committed
550 551 552
  timer.tv_sec = 0;
  timer.tv_usec = 0;
  timerp = NULL;
553
  
Elliot Lee's avatar
Elliot Lee committed
554 555 556 557 558 559
  button_click_time[0] = 0;
  button_click_time[1] = 0;
  button_window[0] = NULL;
  button_window[1] = NULL;
  button_number[0] = -1;
  button_number[1] = -1;
560
  
Tim Janik's avatar
Tim Janik committed
561
  g_atexit (gdk_exit_func);
562
  
Elliot Lee's avatar
Elliot Lee committed
563 564 565 566
  gdk_visual_init ();
  gdk_window_init ();
  gdk_image_init ();
  gdk_input_init ();
567 568 569 570
  gdk_dnd_init ();

  gdk_add_client_message_filter (gdk_wm_protocols, 
				 gdk_wm_protocols_filter, NULL);
571
  
572 573 574 575 576
#ifdef USE_XIM
  /* initialize XIM Protocol variables */
  xim_using = FALSE;
  xim_im = NULL;
  xim_styles = NULL;
577 578 579 580
  if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
    gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
  if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
    gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
581 582
  xim_ic = NULL;
  xim_window = (GdkWindow*)NULL;
583
  
584 585
  gdk_im_open (NULL, NULL, NULL);
#endif
586
  
587
  gdk_initialized = 1;
Elliot Lee's avatar
Elliot Lee committed
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
}

/*
 *--------------------------------------------------------------
 * 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
gdk_exit (int errorcode)
{
612 613 614
  /* de-initialisation is done by the gdk_exit_funct(),
     no need to do this here (Alex J.) */
  exit (errorcode);
Elliot Lee's avatar
Elliot Lee committed
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
}

/*
 *--------------------------------------------------------------
 * gdk_set_locale
 *
 * Arguments:
 *
 * Results:
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

gchar*
631
gdk_set_locale (void)
Elliot Lee's avatar
Elliot Lee committed
632 633
{
  if (!setlocale (LC_ALL,""))
634 635
    g_message ("locale not supported by C library");
  
Elliot Lee's avatar
Elliot Lee committed
636 637
  if (!XSupportsLocale ())
    {
638
      g_message ("locale not supported by Xlib, locale set to C");
Elliot Lee's avatar
Elliot Lee committed
639 640
      setlocale (LC_ALL, "C");
    }
641
  
Elliot Lee's avatar
Elliot Lee committed
642 643
  if (!XSetLocaleModifiers (""))
    {
644
      g_message ("can not set locale modifiers");
Elliot Lee's avatar
Elliot Lee committed
645
    }
646
  
Elliot Lee's avatar
Elliot Lee committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
  return setlocale (LC_ALL,NULL);
}

/*
 *--------------------------------------------------------------
 * gdk_events_pending
 *
 *   Returns the number of events pending on the queue.
 *   These events have already been read from the server
 *   connection.
 *
 * Arguments:
 *
 * Results:
 *   Returns the number of events on XLib's event queue.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

gint
669
gdk_events_pending (void)
Elliot Lee's avatar
Elliot Lee committed
670
{
Owen Taylor's avatar
Owen Taylor committed
671 672
  gint result;
  GList *tmp_list;
673
  
Owen Taylor's avatar
Owen Taylor committed
674
  result = XPending (gdk_display);
675
  
Owen Taylor's avatar
Owen Taylor committed
676 677 678 679 680 681 682 683
  tmp_list = putback_events;
  while (tmp_list)
    {
      result++;
      tmp_list = tmp_list->next;
    }
  
  return result;
Elliot Lee's avatar
Elliot Lee committed
684 685
}

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
/*
 *--------------------------------------------------------------
 * gdk_event_get_graphics_expose
 *
 *   Waits for a GraphicsExpose or NoExpose event
 *
 * Arguments:
 *
 * Results: 
 *   For GraphicsExpose events, returns a pointer to the event
 *   converted into a GdkEvent Otherwise, returns NULL.
 *
 * Side effects:
 *
 *-------------------------------------------------------------- */

static Bool
graphics_expose_predicate  (Display  *display,
			    XEvent   *xevent,
			    XPointer  arg)
{
  GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
708 709
  
  g_return_val_if_fail (private != NULL, False);
710
  
711 712 713 714 715 716 717 718 719 720 721 722 723
  if ((xevent->xany.window == private->xwindow) &&
      ((xevent->xany.type == GraphicsExpose) ||
       (xevent->xany.type == NoExpose)))
    return True;
  else
    return False;
}

GdkEvent *
gdk_event_get_graphics_expose (GdkWindow *window)
{
  XEvent xevent;
  GdkEvent *event;
724 725
  
  g_return_val_if_fail (window != NULL, NULL);
726
  
727
  XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
728
  
729 730 731
  if (xevent.xany.type == GraphicsExpose)
    {
      event = gdk_event_new ();
732
      
733 734 735 736 737 738
      if (gdk_event_translate (event, &xevent))
	return event;
      else
	gdk_event_free (event);
    }
  
739
  return NULL;	
740 741
}

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
/************************
 * Exposure compression *
 ************************/

/*
 * The following implements simple exposure compression. It is
 * modelled after the way Xt does exposure compression - in
 * particular compress_expose = XtExposeCompressMultiple.
 * It compress consecutive sequences of exposure events,
 * but not sequences that cross other events. (This is because
 * if it crosses a ConfigureNotify, we could screw up and
 * mistakenly compress the exposures generated for the new
 * size - could we just check for ConfigureNotify?)
 *
 * Xt compresses to a region / bounding rectangle, we compress
 * to two rectangles, and try find the two rectangles of minimal
 * area for this - this is supposed to handle the typical
 * L-shaped regions generated by OpaqueMove.
 */

/* Given three rectangles, find the two rectangles that cover
 * them with the smallest area.
 */
static void
gdk_add_rect_to_rects (GdkRectangle *rect1,
		       GdkRectangle *rect2, 
		       GdkRectangle *new_rect)
{
  GdkRectangle t1, t2, t3;
  gint size1, size2, size3;

  gdk_rectangle_union (rect1, rect2, &t1);
  gdk_rectangle_union (rect1, new_rect, &t2);
  gdk_rectangle_union (rect2, new_rect, &t3);

  size1 = t1.width * t1.height + new_rect->width * new_rect->height;
  size2 = t2.width * t2.height + rect2->width * rect2->height;
  size3 = t1.width * t1.height + rect1->width * rect1->height;

  if (size1 < size2)
    {
      if (size1 < size3)
	{
	  *rect1 = t1;
	  *rect2 = *new_rect;
	}
      else
	*rect2 = t3;
    }
  else
    {
      if (size2 < size3)
	*rect1 = t2;
      else
	*rect2 = t3;
    }
}

typedef struct _GdkExposeInfo GdkExposeInfo;

struct _GdkExposeInfo {
  Window window;
  gboolean seen_nonmatching;
};

Bool
expose_predicate (Display *display, XEvent *xevent, XPointer arg)
{
  GdkExposeInfo *info = (GdkExposeInfo *)arg;

  if (xevent->xany.type != Expose)
    {
      info->seen_nonmatching = TRUE;
    }

  if (info->seen_nonmatching || (xevent->xany.window != info->window))
    return FALSE;
  else
    return TRUE;
}

void
gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
{
  gint nrects = 1;
  gint count = 0;
  GdkRectangle rect1;
  GdkRectangle rect2;
  GdkRectangle tmp_rect;
  XEvent tmp_event;
  GdkFilterReturn result;
  GdkExposeInfo info;
  GdkEvent event;

  info.window = xevent->xany.window;
  info.seen_nonmatching = FALSE;
  
  rect1.x = xevent->xexpose.x;
  rect1.y = xevent->xexpose.y;
  rect1.width = xevent->xexpose.width;
  rect1.height = xevent->xexpose.height;

  while (1)
    {
      if (count == 0)
	{
	  if (!XCheckIfEvent (gdk_display, 
			      &tmp_event, 
			      expose_predicate, 
			      (XPointer)&info))
	    break;
	}
      else
	XIfEvent (gdk_display, 
		  &tmp_event, 
		  expose_predicate, 
		  (XPointer)&info);
      
      /* We apply filters here, and if it was filtered, completely
       * ignore the return
       */
      result = gdk_event_apply_filters (xevent, &event,
					window ? 
					  ((GdkWindowPrivate *)window)->filters
					  : gdk_default_filters);
      
      if (result != GDK_FILTER_CONTINUE)
	{
	  if (result == GDK_FILTER_TRANSLATE)
	    gdk_event_put (&event);
	  continue;
	}

      if (nrects == 1)
	{
	  rect2.x = tmp_event.xexpose.x;
	  rect2.y = tmp_event.xexpose.y;
	  rect2.width = tmp_event.xexpose.width;
	  rect2.height = tmp_event.xexpose.height;

	  nrects++;
	}
      else
	{
	  tmp_rect.x = tmp_event.xexpose.x;
	  tmp_rect.y = tmp_event.xexpose.y;
	  tmp_rect.width = tmp_event.xexpose.width;
	  tmp_rect.height = tmp_event.xexpose.height;

	  gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
	}

      count = tmp_event.xexpose.count;
    }

  if (nrects == 2)
    {
      gdk_rectangle_union (&rect1, &rect2, &tmp_rect);

      if ((tmp_rect.width * tmp_rect.height) <
	  2 * (rect1.height * rect1.width +
	       rect2.height * rect2.width))
	{
	  rect1 = tmp_rect;
	  nrects = 1;
	}
    }

  if (nrects == 2)
    {
      event.expose.type = GDK_EXPOSE;
      event.expose.window = window;
      event.expose.area.x = rect2.x;
      event.expose.area.y = rect2.y;
      event.expose.area.width = rect2.width;
      event.expose.area.height = rect2.height;
      event.expose.count = 0;

      gdk_event_put (&event);
    }

  xevent->xexpose.count = nrects - 1;
  xevent->xexpose.x = rect1.x;
  xevent->xexpose.y = rect1.y;
  xevent->xexpose.width = rect1.width;
  xevent->xexpose.height = rect1.height;
}

Elliot Lee's avatar
Elliot Lee committed
930 931 932 933 934 935 936 937 938
/*
 *--------------------------------------------------------------
 * gdk_event_get
 *
 *   Gets the next event.
 *
 * Arguments:
 *
 * Results:
939 940 941
 *   If an event was received that we care about, returns 
 *   a pointer to that event, to be freed with gdk_event_free.
 *   Otherwise, returns NULL. This function will also return
Elliot Lee's avatar
Elliot Lee committed
942 943 944 945 946 947 948 949
 *   before an event is received if the timeout interval
 *   runs out.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

950 951
GdkEvent *
gdk_event_get (void)
Elliot Lee's avatar
Elliot Lee committed
952
{
953
  GdkEvent *event;
Elliot Lee's avatar
Elliot Lee committed
954 955
  GList *temp_list;
  XEvent xevent;
956
  
957
#if 0
Elliot Lee's avatar
Elliot Lee committed
958 959 960 961 962 963
  if (pred)
    {
      temp_list = putback_events;
      while (temp_list)
	{
	  temp_event = temp_list->data;
964
	  
Elliot Lee's avatar
Elliot Lee committed
965 966 967 968 969 970 971 972
	  if ((* pred) (temp_event, data))
	    {
	      if (event)
		*event = *temp_event;
	      putback_events = g_list_remove_link (putback_events, temp_list);
	      g_list_free (temp_list);
	      return TRUE;
	    }
973
	  
Elliot Lee's avatar
Elliot Lee committed
974 975
	  temp_list = temp_list->next;
	}
976
      
Elliot Lee's avatar
Elliot Lee committed
977 978
      event_pred.func = pred;
      event_pred.data = data;
979
      
980
      if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
Elliot Lee's avatar
Elliot Lee committed
981 982 983 984
	if (event)
	  return gdk_event_translate (event, &xevent);
    }
  else
985
#endif
986 987 988 989 990 991 992 993 994 995
    if (putback_events)
      {
	event = putback_events->data;
	
	temp_list = putback_events;
	putback_events = g_list_remove_link (putback_events, temp_list);
	g_list_free_1 (temp_list);
	
	return event;
      }
996 997 998 999 1000 1001 1002 1003 1004 1005
  
  /* Wait for an event to occur or the timeout to elapse.
   * If an event occurs "gdk_event_wait" will return TRUE.
   *  If the timeout elapses "gdk_event_wait" will return
   *  FALSE.
   */
  if (gdk_event_wait ())
    {
      /* If we get here we can rest assurred that an event
       *  has occurred. Read it.
Elliot Lee's avatar
Elliot Lee committed
1006
       */
1007
#ifdef USE_XIM
1008 1009 1010 1011
      gint filter_status;
      if (xim_using && xim_window)
	do
	  {		/* don't dispatch events used by IM */
1012
	    XNextEvent (gdk_display, &xevent);
1013 1014 1015 1016 1017
	    filter_status = XFilterEvent (&xevent, 
					  GDK_WINDOW_XWINDOW (xim_window));
	  } while (filter_status == True);
      else
	XNextEvent (gdk_display, &xevent);
1018
#else
1019
      XNextEvent (gdk_display, &xevent);
1020
#endif
1021
      
1022
      event = gdk_event_new ();
1023
      
1024 1025 1026 1027 1028 1029 1030 1031 1032
      event->any.type = GDK_NOTHING;
      event->any.window = NULL;
      event->any.send_event = FALSE;
      event->any.send_event = xevent.xany.send_event;
      
      if (gdk_event_translate (event, &xevent))
	return event;
      else
	gdk_event_free (event);
Elliot Lee's avatar
Elliot Lee committed
1033
    }
1034
  
1035
  return NULL;
Elliot Lee's avatar
Elliot Lee committed
1036 1037 1038 1039 1040 1041
}

void
gdk_event_put (GdkEvent *event)
{
  GdkEvent *new_event;
1042
  
Elliot Lee's avatar
Elliot Lee committed
1043
  g_return_if_fail (event != NULL);
1044
  
1045
  new_event = gdk_event_copy (event);
1046
  
Elliot Lee's avatar
Elliot Lee committed
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
  putback_events = g_list_prepend (putback_events, new_event);
}

/*
 *--------------------------------------------------------------
 * gdk_event_copy
 *
 *   Copy a event structure into new storage.
 *
 * Arguments:
 *   "event" is the event struct to copy.
 *
 * Results:
 *   A new event structure.  Free it with gdk_event_free.
 *
 * Side effects:
 *   The reference count of the window in the event is increased.
 *
 *--------------------------------------------------------------
 */

static GMemChunk *event_chunk;

1070 1071
static GdkEvent*
gdk_event_new (void)
Elliot Lee's avatar
Elliot Lee committed
1072 1073 1074 1075 1076 1077 1078 1079
{
  GdkEvent *new_event;
  
  if (event_chunk == NULL)
    event_chunk = g_mem_chunk_new ("events",
				   sizeof (GdkEvent),
				   4096,
				   G_ALLOC_AND_FREE);
1080
  
Elliot Lee's avatar
Elliot Lee committed
1081
  new_event = g_chunk_new (GdkEvent, event_chunk);
1082
  
1083 1084 1085 1086 1087 1088 1089 1090 1091
  return new_event;
}

GdkEvent*
gdk_event_copy (GdkEvent *event)
{
  GdkEvent *new_event;
  
  g_return_val_if_fail (event != NULL, NULL);
1092
  
1093
  new_event = gdk_event_new ();
1094
  
Elliot Lee's avatar
Elliot Lee committed
1095 1096
  *new_event = *event;
  gdk_window_ref (new_event->any.window);
1097
  
Owen Taylor's avatar
Owen Taylor committed
1098 1099 1100 1101 1102 1103
  switch (event->any.type)
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      new_event->key.string = g_strdup (event->key.string);
      break;
1104
      
Owen Taylor's avatar
Owen Taylor committed
1105 1106 1107 1108 1109
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      if (event->crossing.subwindow != NULL)
	gdk_window_ref (event->crossing.subwindow);
      break;
1110
      
1111 1112 1113 1114 1115 1116 1117
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DRAG_STATUS:
    case GDK_DROP_START:
    case GDK_DROP_FINISHED:
      gdk_drag_context_ref (event->dnd.context);
Owen Taylor's avatar
Owen Taylor committed
1118
      break;
1119

1120
      
Owen Taylor's avatar
Owen Taylor committed
1121 1122 1123
    default:
      break;
    }
1124
  
Elliot Lee's avatar
Elliot Lee committed
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
  return new_event;
}

/*
 *--------------------------------------------------------------
 * gdk_event_free
 *
 *   Free a event structure obtained from gdk_event_copy.  Do not use
 *   with other event structures.
 *
 * Arguments:
 *   "event" is the event struct to free.
 *
 * Results:
 *
 * Side effects:
 *   The reference count of the window in the event is decreased and
 *   might be freed, too.
 *
 *-------------------------------------------------------------- */

void
gdk_event_free (GdkEvent *event)
{
  g_assert (event_chunk != NULL);
  g_return_if_fail (event != NULL);
1151
  
1152 1153
  if (event->any.window)
    gdk_window_unref (event->any.window);
1154
  
Owen Taylor's avatar
Owen Taylor committed
1155 1156 1157 1158 1159 1160
  switch (event->any.type)
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      g_free (event->key.string);
      break;
1161
      
Owen Taylor's avatar
Owen Taylor committed
1162 1163 1164 1165 1166
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      if (event->crossing.subwindow != NULL)
	gdk_window_unref (event->crossing.subwindow);
      break;
1167
      
1168 1169 1170 1171 1172 1173 1174
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DRAG_STATUS:
    case GDK_DROP_START:
    case GDK_DROP_FINISHED:
      gdk_drag_context_unref (event->dnd.context);
Elliot Lee's avatar
Elliot Lee committed
1175
      break;
1176

1177
      
Owen Taylor's avatar
Owen Taylor committed
1178 1179 1180
    default:
      break;
    }
1181
  
Elliot Lee's avatar
Elliot Lee committed
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
  g_mem_chunk_free (event_chunk, event);
}

/*
 *--------------------------------------------------------------
 * gdk_set_show_events
 *
 *   Turns on/off the showing of events.
 *
 * Arguments:
 *   "show_events" is a boolean describing whether or
 *   not to show the events gdk receives.
 *
 * Results:
 *
 * Side effects:
 *   When "show_events" is TRUE, calls to "gdk_event_get"
 *   will output debugging informatin regarding the event
 *   received to stdout.
 *
 *--------------------------------------------------------------
 */

1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
/*
 *--------------------------------------------------------------
 * gdk_event_get_time:
 *    Get the timestamp from an event.
 *   arguments:
 *     event:
 *   results:
 *    The event's time stamp, if it has one, otherwise
 *    GDK_CURRENT_TIME.
 *--------------------------------------------------------------
 */

guint32
gdk_event_get_time (GdkEvent *event)
{
  if (event)
    switch (event->type)
      {
      case GDK_MOTION_NOTIFY:
	return event->motion.time;
      case GDK_BUTTON_PRESS:
      case GDK_2BUTTON_PRESS:
      case GDK_3BUTTON_PRESS:
      case GDK_BUTTON_RELEASE:
	return event->button.time;
      case GDK_KEY_PRESS:
      case GDK_KEY_RELEASE:
	return event->key.time;
      case GDK_ENTER_NOTIFY:
      case GDK_LEAVE_NOTIFY:
	return event->crossing.time;
      case GDK_PROPERTY_NOTIFY:
	return event->property.time;
      case GDK_SELECTION_CLEAR:
      case GDK_SELECTION_REQUEST:
      case GDK_SELECTION_NOTIFY:
	return event->selection.time;
      case GDK_PROXIMITY_IN:
      case GDK_PROXIMITY_OUT:
	return event->proximity.time;
      case GDK_DRAG_ENTER:
      case GDK_DRAG_LEAVE:
      case GDK_DRAG_MOTION:
      case GDK_DRAG_STATUS:
      case GDK_DROP_START:
      case GDK_DROP_FINISHED:
	return event->dnd.time;
      default:			/* use current time */
	break;
      }
  
  return GDK_CURRENT_TIME;
}

Elliot Lee's avatar
Elliot Lee committed
1259 1260 1261
void
gdk_set_show_events (int show_events)
{
1262 1263 1264 1265
  if (show_events)
    gdk_debug_flags |= GDK_DEBUG_EVENTS;
  else
    gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
Elliot Lee's avatar
Elliot Lee committed
1266 1267 1268 1269 1270 1271 1272 1273 1274
}

void
gdk_set_use_xshm (gint use_xshm)
{
  gdk_use_xshm = use_xshm;
}

gint
1275
gdk_get_show_events (void)
Elliot Lee's avatar
Elliot Lee committed
1276
{
1277
  return gdk_debug_flags & GDK_DEBUG_EVENTS;
Elliot Lee's avatar
Elliot Lee committed
1278 1279 1280
}

gint
1281
gdk_get_use_xshm (void)
Elliot Lee's avatar
Elliot Lee committed
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
{
  return gdk_use_xshm;
}

/*
 *--------------------------------------------------------------
 * gdk_time_get
 *
 *   Get the number of milliseconds since the library was
 *   initialized.
 *
 * Arguments:
 *
 * Results:
 *   The time since the library was initialized is returned.
 *   This time value is accurate to milliseconds even though
 *   a more accurate time down to the microsecond could be
 *   returned.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

guint32
1307
gdk_time_get (void)
Elliot Lee's avatar
Elliot Lee committed
1308 1309 1310 1311
{
  struct timeval end;
  struct timeval elapsed;
  guint32 milliseconds;
1312
  
Elliot Lee's avatar
Elliot Lee committed
1313
  X_GETTIMEOFDAY (&end);
1314
  
Elliot Lee's avatar
Elliot Lee committed
1315 1316 1317 1318 1319 1320 1321
  if (start.tv_usec > end.tv_usec)
    {
      end.tv_usec += 1000000;
      end.tv_sec--;
    }
  elapsed.tv_sec = end.tv_sec - start.tv_sec;
  elapsed.tv_usec = end.tv_usec - start.tv_usec;
1322
  
Elliot Lee's avatar
Elliot Lee committed
1323
  milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1324
  
Elliot Lee's avatar
Elliot Lee committed
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
  return milliseconds;
}

/*
 *--------------------------------------------------------------
 * gdk_timer_get
 *
 *   Returns the current timer.
 *
 * Arguments:
 *
 * Results:
 *   Returns the current timer interval. This interval is
 *   in units of milliseconds.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */

guint32
1346
gdk_timer_get (void)
Elliot Lee's avatar
Elliot Lee committed
1347 1348 1349 1350 1351 1352 1353 1354