source: trunk/third/gtk/gdk/gdk.c @ 17071

Revision 17071, 34.0 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17070, which included commits to RCS files with non-trunk default branches.
Line 
1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include "config.h"
28
29#include <ctype.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <limits.h>
34#include <errno.h>
35
36#ifdef HAVE_SYS_SELECT_H
37#include <sys/select.h>
38#endif /* HAVE_SYS_SELECT_H_ */
39
40#define XLIB_ILLEGAL_ACCESS
41#include <X11/Xatom.h>
42#include <X11/Xlib.h>
43#include <X11/Xos.h>
44#include <X11/Xutil.h>
45#include <X11/cursorfont.h>
46#include "gdk.h"
47#include "gdkprivate.h"
48#include "gdkinput.h"
49#include "gdkx.h"
50#include "gdki18n.h"
51#include "gdkkeysyms.h"
52
53#ifndef X_GETTIMEOFDAY
54#define X_GETTIMEOFDAY(tv)  gettimeofday (tv, NULL)
55#endif /* X_GETTIMEOFDAY */
56
57
58typedef struct _GdkPredicate  GdkPredicate;
59typedef struct _GdkErrorTrap  GdkErrorTrap;
60
61struct _GdkPredicate
62{
63  GdkEventFunc func;
64  gpointer data;
65};
66
67struct _GdkErrorTrap
68{
69  gint error_warnings;
70  gint error_code;
71};
72
73/*
74 * Private function declarations
75 */
76
77#ifndef HAVE_XCONVERTCASE
78static void      gdkx_XConvertCase      (KeySym        symbol,
79                                         KeySym       *lower,
80                                         KeySym       *upper);
81#define XConvertCase gdkx_XConvertCase
82#endif
83
84static void         gdk_exit_func                (void);
85static int          gdk_x_error                  (Display     *display,
86                                                  XErrorEvent *error);
87static int          gdk_x_io_error               (Display     *display);
88
89GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
90                                         GdkEvent  *event,
91                                         gpointer   data);
92
93/* Private variable declarations
94 */
95static int gdk_initialized = 0;                     /* 1 if the library is initialized,
96                                                     * 0 otherwise.
97                                                     */
98
99static struct timeval start;                        /* The time at which the library was
100                                                     *  last initialized.
101                                                     */
102static struct timeval timer;                        /* Timeout interval to use in the call
103                                                     *  to "select". This is used in
104                                                     *  conjunction with "timerp" to create
105                                                     *  a maximum time to wait for an event
106                                                     *  to arrive.
107                                                     */
108static struct timeval *timerp;                      /* The actual timer passed to "select"
109                                                     *  This may be NULL, in which case
110                                                     *  "select" will block until an event
111                                                     *  arrives.
112                                                     */
113static guint32 timer_val;                           /* The timeout length as specified by
114                                                     *  the user in milliseconds.
115                                                     */
116static gint autorepeat;
117
118static GSList *gdk_error_traps = NULL;               /* List of error traps */
119static GSList *gdk_error_trap_free_list = NULL;      /* Free list */
120
121#ifdef G_ENABLE_DEBUG
122static const GDebugKey gdk_debug_keys[] = {
123  {"events",        GDK_DEBUG_EVENTS},
124  {"misc",          GDK_DEBUG_MISC},
125  {"dnd",           GDK_DEBUG_DND},
126  {"color-context", GDK_DEBUG_COLOR_CONTEXT},
127  {"xim",           GDK_DEBUG_XIM}
128};
129
130static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
131
132#endif /* G_ENABLE_DEBUG */
133
134static const char *
135get_option (char ***argv,
136            gint    argc,
137            int    *i_inout)
138{
139  gchar *equal_pos;
140  const gchar *result = NULL;
141  gint i = *i_inout;
142  const gchar *orig = (*argv)[i];
143
144  equal_pos = strchr ((*argv)[i], '=');
145  (*argv)[i] = NULL;
146
147  if (equal_pos)
148    {
149      result = equal_pos + 1;
150    }
151  else
152    {
153      if ((i + 1) < argc && (*argv)[i + 1])
154        {
155          i++;
156          result = (*argv)[i];
157          (*argv)[i] = NULL;
158        }
159      else
160        {
161          g_warning ("Option '%s' requires an argument.", orig);
162        }
163    }
164
165  *i_inout = i;
166  return result;
167}
168
169/*
170 *--------------------------------------------------------------
171 * gdk_init_heck
172 *
173 *   Initialize the library for use.
174 *
175 * Arguments:
176 *   "argc" is the number of arguments.
177 *   "argv" is an array of strings.
178 *
179 * Results:
180 *   "argc" and "argv" are modified to reflect any arguments
181 *   which were not handled. (Such arguments should either
182 *   be handled by the application or dismissed). If initialization
183 *   fails, returns FALSE, otherwise TRUE.
184 *
185 * Side effects:
186 *   The library is initialized.
187 *
188 *--------------------------------------------------------------
189 */
190
191gboolean
192gdk_init_check (int      *argc,
193                char ***argv)
194{
195  XKeyboardState keyboard_state;
196  gint synchronize;
197  gint i, j, k;
198  XClassHint *class_hint;
199  gchar **argv_orig = NULL;
200  gint argc_orig = 0;
201  const gchar *option;
202 
203  if (gdk_initialized)
204    return TRUE;
205 
206  if (g_thread_supported ())
207    gdk_threads_mutex = g_mutex_new ();
208 
209  if (argc && argv)
210    {
211      argc_orig = *argc;
212     
213      argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
214      for (i = 0; i < argc_orig; i++)
215        argv_orig[i] = g_strdup ((*argv)[i]);
216      argv_orig[argc_orig] = NULL;
217    }
218 
219  X_GETTIMEOFDAY (&start);
220 
221  gdk_display_name = NULL;
222 
223  XSetErrorHandler (gdk_x_error);
224  XSetIOErrorHandler (gdk_x_io_error);
225 
226  synchronize = FALSE;
227 
228#ifdef G_ENABLE_DEBUG
229  {
230    gchar *debug_string = getenv("GDK_DEBUG");
231    if (debug_string != NULL)
232      gdk_debug_flags = g_parse_debug_string (debug_string,
233                                              (GDebugKey *) gdk_debug_keys,
234                                              gdk_ndebug_keys);
235  }
236#endif  /* G_ENABLE_DEBUG */
237 
238  if (argc && argv)
239    {
240      if (*argc > 0)
241        {
242          gchar *d;
243         
244          d = strrchr((*argv)[0],'/');
245          if (d != NULL)
246            g_set_prgname (d + 1);
247          else
248            g_set_prgname ((*argv)[0]);
249        }
250     
251      for (i = 1; i < *argc;)
252        {
253#ifdef G_ENABLE_DEBUG     
254          if ((strcmp ("--gdk-debug", (*argv)[i]) == 0) ||
255              (strncmp ("--gdk-debug=", (*argv)[i], 12) == 0))
256            {
257              option = get_option (argv, *argc, &i);
258
259              if (option)
260                gdk_debug_flags |= g_parse_debug_string (option,
261                                                         (GDebugKey *) gdk_debug_keys,
262                                                         gdk_ndebug_keys);
263            }
264          else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
265                   (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
266            {
267              option = get_option (argv, *argc, &i);
268
269              if (option)
270                gdk_debug_flags &= ~g_parse_debug_string (option,
271                                                          (GDebugKey *) gdk_debug_keys,
272                                                          gdk_ndebug_keys);
273            }
274          else
275#endif /* G_ENABLE_DEBUG */
276            if ((strcmp ("--display", (*argv)[i]) == 0) ||
277                (strncmp ("--display=", (*argv)[i], 10) == 0))
278              {
279                option = get_option (argv, *argc, &i);
280
281                if (option)
282                  {
283                    if (gdk_display_name)
284                      g_free (gdk_display_name);
285                     
286                    gdk_display_name = g_strdup (option);
287                  }
288              }
289            else if (strcmp ("--sync", (*argv)[i]) == 0)
290              {
291                (*argv)[i] = NULL;
292                synchronize = TRUE;
293              }
294            else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
295              {
296                (*argv)[i] = NULL;
297                gdk_use_xshm = FALSE;
298              }
299            else if ((strcmp ("--name", (*argv)[i]) == 0) ||
300                     (strncmp ("--name=", (*argv)[i], 7) == 0))
301              {
302                option = get_option (argv, *argc, &i);
303
304                if (option)
305                  g_set_prgname (option);
306              }
307            else if ((strcmp ("--class", (*argv)[i]) == 0) ||
308                     (strncmp ("--class=", (*argv)[i], 8) == 0))
309              {
310                option = get_option (argv, *argc, &i);
311
312                if (option)
313                  {
314                    if (gdk_progclass)
315                      g_free (gdk_progclass);
316                   
317                    gdk_progclass = g_strdup (option);
318                  }
319              }
320#ifdef XINPUT_GXI
321            else if ((strcmp ("--gxid_host", (*argv)[i]) == 0) ||
322                     (strncmp ("--gxid_host=", (*argv)[i], 12) == 0))
323              {
324                option = get_option (argv, *argc, &i);
325
326                if (option)
327                  {
328                    if (gdk_input_gxid_host)
329                      g_free (gdk_input_gxid_host);
330                   
331                    gdk_input_gxid_host = g_strdup (option);
332                  }
333              }
334            else if ((strcmp ("--gxid_port", (*argv)[i]) == 0) ||
335                     (strncmp ("--gxid_port=", (*argv)[i], 12) == 0))
336              {
337                option = get_option (argv, *argc, &i);
338
339                if (option)
340                  gdk_input_gxid_port = atoi (option);
341              }
342#endif
343#ifdef USE_XIM
344            else if ((strcmp ("--xim-preedit", (*argv)[i]) == 0) ||
345                     (strncmp ("--xim-preedit=", (*argv)[i], 14) == 0))
346              {
347                option = get_option (argv, *argc, &i);
348
349                if (option)
350                  {
351                    if (strcmp ("none", option) == 0)
352                      gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
353                    else if (strcmp ("nothing", option) == 0)
354                      gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
355                    else if (strcmp ("area", option) == 0)
356                      gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
357                    else if (strcmp ("position", option) == 0)
358                      gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
359                    else if (strcmp ("callbacks", option) == 0)
360                      gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
361                    else
362                      g_warning ("Argument '%s' for --xim-preedit not understood", option);
363                     
364                  }
365              }
366            else if ((strcmp ("--xim-status", (*argv)[i]) == 0) ||
367                     (strncmp ("--xim-status=", (*argv)[i], 13) == 0))
368              {
369                option = get_option (argv, *argc, &i);
370               
371                if (option)
372                  {
373                    if (strcmp ("none", option) == 0)
374                      gdk_im_set_best_style (GDK_IM_STATUS_NONE);
375                    else if (strcmp ("nothing", option) == 0)
376                      gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
377                    else if (strcmp ("area", option) == 0)
378                      gdk_im_set_best_style (GDK_IM_STATUS_AREA);
379                    else if (strcmp ("callbacks", option) == 0)
380                      gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
381                    else
382                      g_warning ("Argumetn '%s' for --xim-status not understood", option);
383                  }
384              }
385#endif
386         
387          i++;
388        }
389     
390      for (i = 1; i < *argc; i++)
391        {
392          for (k = i; k < *argc; k++)
393            if ((*argv)[k] != NULL)
394              break;
395         
396          if (k > i)
397            {
398              k -= i;
399              for (j = i + k; j < *argc; j++)
400                (*argv)[j-k] = (*argv)[j];
401              *argc -= k;
402            }
403        }
404    }
405  else
406    {
407      g_set_prgname ("<unknown>");
408    }
409 
410  GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ()));
411 
412  gdk_display = XOpenDisplay (gdk_display_name);
413  if (!gdk_display)
414    return FALSE;
415 
416  if (synchronize)
417    XSynchronize (gdk_display, True);
418 
419  gdk_screen = DefaultScreen (gdk_display);
420  gdk_root_window = RootWindow (gdk_display, gdk_screen);
421 
422  gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
423                                          10, 10, 10, 10, 0, 0 , 0);
424  class_hint = XAllocClassHint();
425  class_hint->res_name = g_get_prgname ();
426  if (gdk_progclass == NULL)
427    {
428      gdk_progclass = g_strdup (g_get_prgname ());
429      gdk_progclass[0] = toupper (gdk_progclass[0]);
430    }
431  class_hint->res_class = gdk_progclass;
432  XmbSetWMProperties (gdk_display, gdk_leader_window,
433                      NULL, NULL, argv_orig, argc_orig,
434                      NULL, NULL, class_hint);
435  XFree (class_hint);
436 
437  for (i = 0; i < argc_orig; i++)
438    g_free(argv_orig[i]);
439  g_free(argv_orig);
440 
441  gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", False);
442  gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", False);
443  gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", False);
444  gdk_wm_window_protocols[0] = gdk_wm_delete_window;
445  gdk_wm_window_protocols[1] = gdk_wm_take_focus;
446  gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
447 
448  XGetKeyboardControl (gdk_display, &keyboard_state);
449  autorepeat = keyboard_state.global_auto_repeat;
450 
451  timer.tv_sec = 0;
452  timer.tv_usec = 0;
453  timerp = NULL;
454 
455  g_atexit (gdk_exit_func);
456 
457  gdk_events_init ();
458  gdk_visual_init ();
459  gdk_window_init ();
460  gdk_image_init ();
461  gdk_input_init ();
462  gdk_dnd_init ();
463
464#ifdef USE_XIM
465  gdk_im_open ();
466#endif
467 
468  gdk_initialized = 1;
469
470  return TRUE;
471}
472
473void
474gdk_init (int *argc, char ***argv)
475{
476  if (!gdk_init_check (argc, argv))
477    {
478      g_warning ("cannot open display: %s", gdk_get_display ());
479      exit(1);
480    }
481}
482
483/*
484 *--------------------------------------------------------------
485 * gdk_exit
486 *
487 *   Restores the library to an un-itialized state and exits
488 *   the program using the "exit" system call.
489 *
490 * Arguments:
491 *   "errorcode" is the error value to pass to "exit".
492 *
493 * Results:
494 *   Allocated structures are freed and the program exits
495 *   cleanly.
496 *
497 * Side effects:
498 *
499 *--------------------------------------------------------------
500 */
501
502void
503gdk_exit (int errorcode)
504{
505  /* de-initialisation is done by the gdk_exit_funct(),
506     no need to do this here (Alex J.) */
507  exit (errorcode);
508}
509
510void
511gdk_set_use_xshm (gboolean use_xshm)
512{
513  gdk_use_xshm = use_xshm;
514}
515
516gboolean
517gdk_get_use_xshm (void)
518{
519  return gdk_use_xshm;
520}
521
522/*
523 *--------------------------------------------------------------
524 * gdk_time_get
525 *
526 *   Get the number of milliseconds since the library was
527 *   initialized.
528 *
529 * Arguments:
530 *
531 * Results:
532 *   The time since the library was initialized is returned.
533 *   This time value is accurate to milliseconds even though
534 *   a more accurate time down to the microsecond could be
535 *   returned.
536 *
537 * Side effects:
538 *
539 *--------------------------------------------------------------
540 */
541
542guint32
543gdk_time_get (void)
544{
545  struct timeval end;
546  struct timeval elapsed;
547  guint32 milliseconds;
548 
549  X_GETTIMEOFDAY (&end);
550 
551  if (start.tv_usec > end.tv_usec)
552    {
553      end.tv_usec += 1000000;
554      end.tv_sec--;
555    }
556  elapsed.tv_sec = end.tv_sec - start.tv_sec;
557  elapsed.tv_usec = end.tv_usec - start.tv_usec;
558 
559  milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
560 
561  return milliseconds;
562}
563
564/*
565 *--------------------------------------------------------------
566 * gdk_timer_get
567 *
568 *   Returns the current timer.
569 *
570 * Arguments:
571 *
572 * Results:
573 *   Returns the current timer interval. This interval is
574 *   in units of milliseconds.
575 *
576 * Side effects:
577 *
578 *--------------------------------------------------------------
579 */
580
581guint32
582gdk_timer_get (void)
583{
584  return timer_val;
585}
586
587/*
588 *--------------------------------------------------------------
589 * gdk_timer_set
590 *
591 *   Sets the timer interval.
592 *
593 * Arguments:
594 *   "milliseconds" is the new value for the timer.
595 *
596 * Results:
597 *
598 * Side effects:
599 *   Calls to "gdk_event_get" will last for a maximum
600 *   of time of "milliseconds". However, a value of 0
601 *   milliseconds will cause "gdk_event_get" to block
602 *   indefinately until an event is received.
603 *
604 *--------------------------------------------------------------
605 */
606
607void
608gdk_timer_set (guint32 milliseconds)
609{
610  timer_val = milliseconds;
611  timer.tv_sec = milliseconds / 1000;
612  timer.tv_usec = (milliseconds % 1000) * 1000;
613 
614}
615
616void
617gdk_timer_enable (void)
618{
619  timerp = &timer;
620}
621
622void
623gdk_timer_disable (void)
624{
625  timerp = NULL;
626}
627
628/*
629 *--------------------------------------------------------------
630 * gdk_pointer_grab
631 *
632 *   Grabs the pointer to a specific window
633 *
634 * Arguments:
635 *   "window" is the window which will receive the grab
636 *   "owner_events" specifies whether events will be reported as is,
637 *     or relative to "window"
638 *   "event_mask" masks only interesting events
639 *   "confine_to" limits the cursor movement to the specified window
640 *   "cursor" changes the cursor for the duration of the grab
641 *   "time" specifies the time
642 *
643 * Results:
644 *
645 * Side effects:
646 *   requires a corresponding call to gdk_pointer_ungrab
647 *
648 *--------------------------------------------------------------
649 */
650
651gint
652gdk_pointer_grab (GdkWindow *     window,
653                  gint            owner_events,
654                  GdkEventMask    event_mask,
655                  GdkWindow *     confine_to,
656                  GdkCursor *     cursor,
657                  guint32         time)
658{
659  /*  From gdkwindow.c  */
660  gint return_val;
661  GdkWindowPrivate *window_private;
662  GdkWindowPrivate *confine_to_private;
663  GdkCursorPrivate *cursor_private;
664  guint xevent_mask;
665  Window xwindow;
666  Window xconfine_to;
667  Cursor xcursor;
668  int i;
669 
670  g_return_val_if_fail (window != NULL, 0);
671 
672  window_private = (GdkWindowPrivate*) window;
673  confine_to_private = (GdkWindowPrivate*) confine_to;
674  cursor_private = (GdkCursorPrivate*) cursor;
675 
676  xwindow = window_private->xwindow;
677 
678  if (!confine_to || confine_to_private->destroyed)
679    xconfine_to = None;
680  else
681    xconfine_to = confine_to_private->xwindow;
682 
683  if (!cursor)
684    xcursor = None;
685  else
686    xcursor = cursor_private->xcursor;
687 
688 
689  xevent_mask = 0;
690  for (i = 0; i < gdk_nevent_masks; i++)
691    {
692      if (event_mask & (1 << (i + 1)))
693        xevent_mask |= gdk_event_mask_table[i];
694    }
695 
696  if (gdk_input_vtable.grab_pointer)
697    return_val = gdk_input_vtable.grab_pointer (window,
698                                                owner_events,
699                                                event_mask,
700                                                confine_to,
701                                                time);
702  else
703    return_val = Success;
704 
705  if (return_val == Success)
706    {
707      if (!window_private->destroyed)
708        return_val = XGrabPointer (window_private->xdisplay,
709                                   xwindow,
710                                   owner_events,
711                                   xevent_mask,
712                                   GrabModeAsync, GrabModeAsync,
713                                   xconfine_to,
714                                   xcursor,
715                                   time);
716      else
717        return_val = AlreadyGrabbed;
718    }
719 
720  if (return_val == GrabSuccess)
721    gdk_xgrab_window = window_private;
722 
723  return return_val;
724}
725
726/*
727 *--------------------------------------------------------------
728 * gdk_pointer_ungrab
729 *
730 *   Releases any pointer grab
731 *
732 * Arguments:
733 *
734 * Results:
735 *
736 * Side effects:
737 *
738 *--------------------------------------------------------------
739 */
740
741void
742gdk_pointer_ungrab (guint32 time)
743{
744  if (gdk_input_vtable.ungrab_pointer)
745    gdk_input_vtable.ungrab_pointer (time);
746 
747  XUngrabPointer (gdk_display, time);
748  gdk_xgrab_window = NULL;
749}
750
751/*
752 *--------------------------------------------------------------
753 * gdk_pointer_is_grabbed
754 *
755 *   Tell wether there is an active x pointer grab in effect
756 *
757 * Arguments:
758 *
759 * Results:
760 *
761 * Side effects:
762 *
763 *--------------------------------------------------------------
764 */
765
766gboolean
767gdk_pointer_is_grabbed (void)
768{
769  return gdk_xgrab_window != NULL;
770}
771
772/*
773 *--------------------------------------------------------------
774 * gdk_keyboard_grab
775 *
776 *   Grabs the keyboard to a specific window
777 *
778 * Arguments:
779 *   "window" is the window which will receive the grab
780 *   "owner_events" specifies whether events will be reported as is,
781 *     or relative to "window"
782 *   "time" specifies the time
783 *
784 * Results:
785 *
786 * Side effects:
787 *   requires a corresponding call to gdk_keyboard_ungrab
788 *
789 *--------------------------------------------------------------
790 */
791
792gint
793gdk_keyboard_grab (GdkWindow *     window,
794                   gint            owner_events,
795                   guint32         time)
796{
797  GdkWindowPrivate *window_private;
798  Window xwindow;
799 
800  g_return_val_if_fail (window != NULL, 0);
801 
802  window_private = (GdkWindowPrivate*) window;
803  xwindow = window_private->xwindow;
804 
805  if (!window_private->destroyed)
806    return XGrabKeyboard (window_private->xdisplay,
807                          xwindow,
808                          owner_events,
809                          GrabModeAsync, GrabModeAsync,
810                          time);
811  else
812    return AlreadyGrabbed;
813}
814
815/*
816 *--------------------------------------------------------------
817 * gdk_keyboard_ungrab
818 *
819 *   Releases any keyboard grab
820 *
821 * Arguments:
822 *
823 * Results:
824 *
825 * Side effects:
826 *
827 *--------------------------------------------------------------
828 */
829
830void
831gdk_keyboard_ungrab (guint32 time)
832{
833  XUngrabKeyboard (gdk_display, time);
834}
835
836/*
837 *--------------------------------------------------------------
838 * gdk_screen_width
839 *
840 *   Return the width of the screen.
841 *
842 * Arguments:
843 *
844 * Results:
845 *
846 * Side effects:
847 *
848 *--------------------------------------------------------------
849 */
850
851gint
852gdk_screen_width (void)
853{
854  gint return_val;
855 
856  return_val = DisplayWidth (gdk_display, gdk_screen);
857 
858  return return_val;
859}
860
861/*
862 *--------------------------------------------------------------
863 * gdk_screen_height
864 *
865 *   Return the height of the screen.
866 *
867 * Arguments:
868 *
869 * Results:
870 *
871 * Side effects:
872 *
873 *--------------------------------------------------------------
874 */
875
876gint
877gdk_screen_height (void)
878{
879  gint return_val;
880 
881  return_val = DisplayHeight (gdk_display, gdk_screen);
882 
883  return return_val;
884}
885
886/*
887 *--------------------------------------------------------------
888 * gdk_screen_width_mm
889 *
890 *   Return the width of the screen in millimeters.
891 *
892 * Arguments:
893 *
894 * Results:
895 *
896 * Side effects:
897 *
898 *--------------------------------------------------------------
899 */
900
901gint
902gdk_screen_width_mm (void)
903{
904  gint return_val;
905 
906  return_val = DisplayWidthMM (gdk_display, gdk_screen);
907 
908  return return_val;
909}
910
911/*
912 *--------------------------------------------------------------
913 * gdk_screen_height
914 *
915 *   Return the height of the screen in millimeters.
916 *
917 * Arguments:
918 *
919 * Results:
920 *
921 * Side effects:
922 *
923 *--------------------------------------------------------------
924 */
925
926gint
927gdk_screen_height_mm (void)
928{
929  gint return_val;
930 
931  return_val = DisplayHeightMM (gdk_display, gdk_screen);
932 
933  return return_val;
934}
935
936/*
937 *--------------------------------------------------------------
938 * gdk_set_sm_client_id
939 *
940 *   Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
941 *   so that the window manager can save our state using the
942 *   X11R6 ICCCM session management protocol. A NULL value should
943 *   be set following disconnection from the session manager to
944 *   remove the SM_CLIENT_ID property.
945 *
946 * Arguments:
947 *
948 *   "sm_client_id" specifies the client id assigned to us by the
949 *   session manager or NULL to remove the property.
950 *
951 * Results:
952 *
953 * Side effects:
954 *
955 *--------------------------------------------------------------
956 */
957
958void
959gdk_set_sm_client_id (const gchar* sm_client_id)
960{
961  if (sm_client_id && strcmp (sm_client_id, ""))
962    {
963      XChangeProperty (gdk_display, gdk_leader_window,
964                       gdk_atom_intern ("SM_CLIENT_ID", FALSE),
965                       XA_STRING, 8, PropModeReplace,
966                       sm_client_id, strlen(sm_client_id));
967    }
968  else
969     XDeleteProperty (gdk_display, gdk_leader_window,
970                      gdk_atom_intern ("SM_CLIENT_ID", FALSE));
971}
972
973void
974gdk_key_repeat_disable (void)
975{
976  XAutoRepeatOff (gdk_display);
977}
978
979void
980gdk_key_repeat_restore (void)
981{
982  if (autorepeat)
983    XAutoRepeatOn (gdk_display);
984  else
985    XAutoRepeatOff (gdk_display);
986}
987
988
989void
990gdk_beep (void)
991{
992  XBell(gdk_display, 100);
993}
994
995/*
996 *--------------------------------------------------------------
997 * gdk_exit_func
998 *
999 *   This is the "atexit" function that makes sure the
1000 *   library gets a chance to cleanup.
1001 *
1002 * Arguments:
1003 *
1004 * Results:
1005 *
1006 * Side effects:
1007 *   The library is un-initialized and the program exits.
1008 *
1009 *--------------------------------------------------------------
1010 */
1011
1012static void
1013gdk_exit_func (void)
1014{
1015  static gboolean in_gdk_exit_func = FALSE;
1016 
1017  /* This is to avoid an infinite loop if a program segfaults in
1018     an atexit() handler (and yes, it does happen, especially if a program
1019     has trounced over memory too badly for even g_message to work) */
1020  if (in_gdk_exit_func == TRUE)
1021    return;
1022  in_gdk_exit_func = TRUE;
1023 
1024  if (gdk_initialized)
1025    {
1026#ifdef USE_XIM
1027      /* cleanup IC */
1028      gdk_ic_cleanup ();
1029      /* close IM */
1030      gdk_im_close ();
1031#endif
1032      gdk_image_exit ();
1033      gdk_input_exit ();
1034      gdk_key_repeat_restore ();
1035     
1036      XCloseDisplay (gdk_display);
1037      gdk_initialized = 0;
1038    }
1039}
1040
1041/*
1042 *--------------------------------------------------------------
1043 * gdk_x_error
1044 *
1045 *   The X error handling routine.
1046 *
1047 * Arguments:
1048 *   "display" is the X display the error orignated from.
1049 *   "error" is the XErrorEvent that we are handling.
1050 *
1051 * Results:
1052 *   Either we were expecting some sort of error to occur,
1053 *   in which case we set the "gdk_error_code" flag, or this
1054 *   error was unexpected, in which case we will print an
1055 *   error message and exit. (Since trying to continue will
1056 *   most likely simply lead to more errors).
1057 *
1058 * Side effects:
1059 *
1060 *--------------------------------------------------------------
1061 */
1062
1063static int
1064gdk_x_error (Display     *display,
1065             XErrorEvent *error)
1066{
1067  if (error->error_code)
1068    {
1069      if (gdk_error_warnings)
1070        {
1071          char buf[64];
1072         
1073          XGetErrorText (display, error->error_code, buf, 63);
1074
1075#ifdef G_ENABLE_DEBUG     
1076          g_error ("%s\n  serial %ld error_code %d request_code %d minor_code %d\n",
1077                   buf,
1078                   error->serial,
1079                   error->error_code,
1080                   error->request_code,
1081                   error->minor_code);
1082#else /* !G_ENABLE_DEBUG */
1083          fprintf (stderr, "Gdk-ERROR **: %s\n  serial %ld error_code %d request_code %d minor_code %d\n",
1084                   buf,
1085                   error->serial,
1086                   error->error_code,
1087                   error->request_code,
1088                   error->minor_code);
1089
1090          exit(1);
1091#endif /* G_ENABLE_DEBUG */
1092        }
1093      gdk_error_code = error->error_code;
1094    }
1095 
1096  return 0;
1097}
1098
1099/*
1100 *--------------------------------------------------------------
1101 * gdk_x_io_error
1102 *
1103 *   The X I/O error handling routine.
1104 *
1105 * Arguments:
1106 *   "display" is the X display the error orignated from.
1107 *
1108 * Results:
1109 *   An X I/O error basically means we lost our connection
1110 *   to the X server. There is not much we can do to
1111 *   continue, so simply print an error message and exit.
1112 *
1113 * Side effects:
1114 *
1115 *--------------------------------------------------------------
1116 */
1117
1118static int
1119gdk_x_io_error (Display *display)
1120{
1121  /* This is basically modelled after the code in XLib. We need
1122   * an explicit error handler here, so we can disable our atexit()
1123   * which would otherwise cause a nice segfault.
1124   * We fprintf(stderr, instead of g_warning() because g_warning()
1125   * could possibly be redirected to a dialog
1126   */
1127  if (errno == EPIPE)
1128    {
1129      fprintf (stderr, "Gdk-ERROR **: X connection to %s broken (explicit kill or server shutdown).\n", gdk_display ? DisplayString (gdk_display) : gdk_get_display());
1130    }
1131  else
1132    {
1133      fprintf (stderr, "Gdk-ERROR **: Fatal IO error %d (%s) on X server %s.\n",
1134               errno, g_strerror (errno),
1135               gdk_display ? DisplayString (gdk_display) : gdk_get_display());
1136    }
1137
1138  /* Disable the atexit shutdown for GDK */
1139  gdk_initialized = 0;
1140 
1141  exit(1);
1142}
1143
1144gchar *
1145gdk_get_display (void)
1146{
1147  return (gchar *)XDisplayName (gdk_display_name);
1148}
1149
1150/*************************************************************
1151 * gdk_error_trap_push:
1152 *     Push an error trap. X errors will be trapped until
1153 *     the corresponding gdk_error_pop(), which will return
1154 *     the error code, if any.
1155 *   arguments:
1156 *     
1157 *   results:
1158 *************************************************************/
1159
1160void
1161gdk_error_trap_push (void)
1162{
1163  GSList *node;
1164  GdkErrorTrap *trap;
1165
1166  if (gdk_error_trap_free_list)
1167    {
1168      node = gdk_error_trap_free_list;
1169      gdk_error_trap_free_list = gdk_error_trap_free_list->next;
1170    }
1171  else
1172    {
1173      node = g_slist_alloc ();
1174      node->data = g_new (GdkErrorTrap, 1);
1175    }
1176
1177  node->next = gdk_error_traps;
1178  gdk_error_traps = node;
1179 
1180  trap = node->data;
1181  trap->error_code = gdk_error_code;
1182  trap->error_warnings = gdk_error_warnings;
1183
1184  gdk_error_code = 0;
1185  gdk_error_warnings = 0;
1186}
1187
1188/*************************************************************
1189 * gdk_error_trap_pop:
1190 *     Pop an error trap added with gdk_error_push()
1191 *   arguments:
1192 *     
1193 *   results:
1194 *     0, if no error occured, otherwise the error code.
1195 *************************************************************/
1196
1197gint
1198gdk_error_trap_pop (void)
1199{
1200  GSList *node;
1201  GdkErrorTrap *trap;
1202  gint result;
1203
1204  g_return_val_if_fail (gdk_error_traps != NULL, 0);
1205
1206  node = gdk_error_traps;
1207  gdk_error_traps = gdk_error_traps->next;
1208
1209  node->next = gdk_error_trap_free_list;
1210  gdk_error_trap_free_list = node;
1211 
1212  result = gdk_error_code;
1213 
1214  trap = node->data;
1215  gdk_error_code = trap->error_code;
1216  gdk_error_warnings = trap->error_warnings;
1217 
1218  return result;
1219}
1220
1221gint
1222gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
1223                 XEvent *event_send)
1224{
1225  Status result;
1226  gint old_warnings = gdk_error_warnings;
1227 
1228  gdk_error_code = 0;
1229 
1230  gdk_error_warnings = 0;
1231  result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
1232  XSync (gdk_display, False);
1233  gdk_error_warnings = old_warnings;
1234 
1235  return result && !gdk_error_code;
1236}
1237
1238#ifndef HAVE_XCONVERTCASE
1239/* compatibility function from X11R6.3, since XConvertCase is not
1240 * supplied by X11R5.
1241 */
1242static void
1243gdkx_XConvertCase (KeySym symbol,
1244                   KeySym *lower,
1245                   KeySym *upper)
1246{
1247  register KeySym sym = symbol;
1248 
1249  g_return_if_fail (lower != NULL);
1250  g_return_if_fail (upper != NULL);
1251 
1252  *lower = sym;
1253  *upper = sym;
1254 
1255  switch (sym >> 8)
1256    {
1257#if     defined (GDK_A) && defined (GDK_Ooblique)
1258    case 0: /* Latin 1 */
1259      if ((sym >= GDK_A) && (sym <= GDK_Z))
1260        *lower += (GDK_a - GDK_A);
1261      else if ((sym >= GDK_a) && (sym <= GDK_z))
1262        *upper -= (GDK_a - GDK_A);
1263      else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
1264        *lower += (GDK_agrave - GDK_Agrave);
1265      else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
1266        *upper -= (GDK_agrave - GDK_Agrave);
1267      else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
1268        *lower += (GDK_oslash - GDK_Ooblique);
1269      else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
1270        *upper -= (GDK_oslash - GDK_Ooblique);
1271      break;
1272#endif  /* LATIN1 */
1273     
1274#if     defined (GDK_Aogonek) && defined (GDK_tcedilla)
1275    case 1: /* Latin 2 */
1276      /* Assume the KeySym is a legal value (ignore discontinuities) */
1277      if (sym == GDK_Aogonek)
1278        *lower = GDK_aogonek;
1279      else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
1280        *lower += (GDK_lstroke - GDK_Lstroke);
1281      else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
1282        *lower += (GDK_scaron - GDK_Scaron);
1283      else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
1284        *lower += (GDK_zcaron - GDK_Zcaron);
1285      else if (sym == GDK_aogonek)
1286        *upper = GDK_Aogonek;
1287      else if (sym >= GDK_lstroke && sym <= GDK_sacute)
1288        *upper -= (GDK_lstroke - GDK_Lstroke);
1289      else if (sym >= GDK_scaron && sym <= GDK_zacute)
1290        *upper -= (GDK_scaron - GDK_Scaron);
1291      else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
1292        *upper -= (GDK_zcaron - GDK_Zcaron);
1293      else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
1294        *lower += (GDK_racute - GDK_Racute);
1295      else if (sym >= GDK_racute && sym <= GDK_tcedilla)
1296        *upper -= (GDK_racute - GDK_Racute);
1297      break;
1298#endif  /* LATIN2 */
1299     
1300#if     defined (GDK_Hstroke) && defined (GDK_Cabovedot)
1301    case 2: /* Latin 3 */
1302      /* Assume the KeySym is a legal value (ignore discontinuities) */
1303      if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
1304        *lower += (GDK_hstroke - GDK_Hstroke);
1305      else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
1306        *lower += (GDK_gbreve - GDK_Gbreve);
1307      else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
1308        *upper -= (GDK_hstroke - GDK_Hstroke);
1309      else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
1310        *upper -= (GDK_gbreve - GDK_Gbreve);
1311      else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
1312        *lower += (GDK_cabovedot - GDK_Cabovedot);
1313      else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
1314        *upper -= (GDK_cabovedot - GDK_Cabovedot);
1315      break;
1316#endif  /* LATIN3 */
1317     
1318#if     defined (GDK_Rcedilla) && defined (GDK_Amacron)
1319    case 3: /* Latin 4 */
1320      /* Assume the KeySym is a legal value (ignore discontinuities) */
1321      if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
1322        *lower += (GDK_rcedilla - GDK_Rcedilla);
1323      else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
1324        *upper -= (GDK_rcedilla - GDK_Rcedilla);
1325      else if (sym == GDK_ENG)
1326        *lower = GDK_eng;
1327      else if (sym == GDK_eng)
1328        *upper = GDK_ENG;
1329      else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
1330        *lower += (GDK_amacron - GDK_Amacron);
1331      else if (sym >= GDK_amacron && sym <= GDK_umacron)
1332        *upper -= (GDK_amacron - GDK_Amacron);
1333      break;
1334#endif  /* LATIN4 */
1335     
1336#if     defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
1337    case 6: /* Cyrillic */
1338      /* Assume the KeySym is a legal value (ignore discontinuities) */
1339      if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
1340        *lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
1341      else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
1342        *upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
1343      else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
1344        *lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
1345      else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
1346        *upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
1347      break;
1348#endif  /* CYRILLIC */
1349     
1350#if     defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
1351    case 7: /* Greek */
1352      /* Assume the KeySym is a legal value (ignore discontinuities) */
1353      if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
1354        *lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
1355      else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
1356               sym != GDK_Greek_iotaaccentdieresis &&
1357               sym != GDK_Greek_upsilonaccentdieresis)
1358        *upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
1359      else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
1360        *lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
1361      else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
1362               sym != GDK_Greek_finalsmallsigma)
1363        *upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
1364      break;
1365#endif  /* GREEK */
1366    }
1367}
1368#endif
1369
1370gchar*
1371gdk_keyval_name (guint        keyval)
1372{
1373  return XKeysymToString (keyval);
1374}
1375
1376guint
1377gdk_keyval_from_name (const gchar *keyval_name)
1378{
1379  g_return_val_if_fail (keyval_name != NULL, 0);
1380 
1381  return XStringToKeysym (keyval_name);
1382}
1383
1384guint
1385gdk_keyval_to_upper (guint        keyval)
1386{
1387  if (keyval)
1388    {
1389      KeySym lower_val = 0;
1390      KeySym upper_val = 0;
1391     
1392      XConvertCase (keyval, &lower_val, &upper_val);
1393      return upper_val;
1394    }
1395  return 0;
1396}
1397
1398guint
1399gdk_keyval_to_lower (guint        keyval)
1400{
1401  if (keyval)
1402    {
1403      KeySym lower_val = 0;
1404      KeySym upper_val = 0;
1405     
1406      XConvertCase (keyval, &lower_val, &upper_val);
1407      return lower_val;
1408    }
1409  return 0;
1410}
1411
1412gboolean
1413gdk_keyval_is_upper (guint        keyval)
1414{
1415  if (keyval)
1416    {
1417      KeySym lower_val = 0;
1418      KeySym upper_val = 0;
1419     
1420      XConvertCase (keyval, &lower_val, &upper_val);
1421      return upper_val == keyval;
1422    }
1423  return TRUE;
1424}
1425
1426gboolean
1427gdk_keyval_is_lower (guint        keyval)
1428{
1429  if (keyval)
1430    {
1431      KeySym lower_val = 0;
1432      KeySym upper_val = 0;
1433     
1434      XConvertCase (keyval, &lower_val, &upper_val);
1435      return lower_val == keyval;
1436    }
1437  return TRUE;
1438}
1439
1440void
1441gdk_threads_enter ()
1442{
1443  GDK_THREADS_ENTER ();
1444}
1445
1446void
1447gdk_threads_leave ()
1448{
1449  GDK_THREADS_LEAVE ();
1450}
1451
Note: See TracBrowser for help on using the repository browser.