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

Revision 17073, 34.0 KB checked in by ghudson, 23 years ago (diff)
Don't specify a bell volume; use the server default.
RevLine 
[14481]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
[15780]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
[14481]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;
[15780]201  const gchar *option;
[14481]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            {
[15780]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);
[14481]263            }
264          else if ((strcmp ("--gdk-no-debug", (*argv)[i]) == 0) ||
265                   (strncmp ("--gdk-no-debug=", (*argv)[i], 15) == 0))
266            {
[15780]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);
[14481]273            }
274          else
275#endif /* G_ENABLE_DEBUG */
[15780]276            if ((strcmp ("--display", (*argv)[i]) == 0) ||
277                (strncmp ("--display=", (*argv)[i], 10) == 0))
[14481]278              {
[15780]279                option = get_option (argv, *argc, &i);
280
281                if (option)
[14481]282                  {
[15780]283                    if (gdk_display_name)
284                      g_free (gdk_display_name);
285                     
286                    gdk_display_name = g_strdup (option);
[14481]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              }
[15780]299            else if ((strcmp ("--name", (*argv)[i]) == 0) ||
300                     (strncmp ("--name=", (*argv)[i], 7) == 0))
[14481]301              {
[15780]302                option = get_option (argv, *argc, &i);
303
304                if (option)
305                  g_set_prgname (option);
[14481]306              }
[15780]307            else if ((strcmp ("--class", (*argv)[i]) == 0) ||
308                     (strncmp ("--class=", (*argv)[i], 8) == 0))
[14481]309              {
[15780]310                option = get_option (argv, *argc, &i);
311
312                if (option)
[14481]313                  {
[15780]314                    if (gdk_progclass)
315                      g_free (gdk_progclass);
316                   
317                    gdk_progclass = g_strdup (option);
[14481]318                  }
319              }
320#ifdef XINPUT_GXI
[15780]321            else if ((strcmp ("--gxid_host", (*argv)[i]) == 0) ||
322                     (strncmp ("--gxid_host=", (*argv)[i], 12) == 0))
[14481]323              {
[15780]324                option = get_option (argv, *argc, &i);
325
326                if (option)
[14481]327                  {
[15780]328                    if (gdk_input_gxid_host)
329                      g_free (gdk_input_gxid_host);
330                   
331                    gdk_input_gxid_host = g_strdup (option);
[14481]332                  }
333              }
[15780]334            else if ((strcmp ("--gxid_port", (*argv)[i]) == 0) ||
335                     (strncmp ("--gxid_port=", (*argv)[i], 12) == 0))
[14481]336              {
[15780]337                option = get_option (argv, *argc, &i);
338
339                if (option)
[17070]340                  gdk_input_gxid_port = atoi (option);
[14481]341              }
342#endif
343#ifdef USE_XIM
[15780]344            else if ((strcmp ("--xim-preedit", (*argv)[i]) == 0) ||
345                     (strncmp ("--xim-preedit=", (*argv)[i], 14) == 0))
[14481]346              {
[15780]347                option = get_option (argv, *argc, &i);
348
349                if (option)
[14481]350                  {
[15780]351                    if (strcmp ("none", option) == 0)
[14481]352                      gdk_im_set_best_style (GDK_IM_PREEDIT_NONE);
[15780]353                    else if (strcmp ("nothing", option) == 0)
[14481]354                      gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING);
[15780]355                    else if (strcmp ("area", option) == 0)
[14481]356                      gdk_im_set_best_style (GDK_IM_PREEDIT_AREA);
[15780]357                    else if (strcmp ("position", option) == 0)
[14481]358                      gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION);
[15780]359                    else if (strcmp ("callbacks", option) == 0)
[14481]360                      gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
[15780]361                    else
362                      g_warning ("Argument '%s' for --xim-preedit not understood", option);
363                     
[14481]364                  }
365              }
[15780]366            else if ((strcmp ("--xim-status", (*argv)[i]) == 0) ||
367                     (strncmp ("--xim-status=", (*argv)[i], 13) == 0))
[14481]368              {
[15780]369                option = get_option (argv, *argc, &i);
370               
371                if (option)
[14481]372                  {
[15780]373                    if (strcmp ("none", option) == 0)
[14481]374                      gdk_im_set_best_style (GDK_IM_STATUS_NONE);
[15780]375                    else if (strcmp ("nothing", option) == 0)
[14481]376                      gdk_im_set_best_style (GDK_IM_STATUS_NOTHING);
[15780]377                    else if (strcmp ("area", option) == 0)
[14481]378                      gdk_im_set_best_style (GDK_IM_STATUS_AREA);
[15780]379                    else if (strcmp ("callbacks", option) == 0)
[14481]380                      gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
[15780]381                    else
382                      g_warning ("Argumetn '%s' for --xim-status not understood", option);
[14481]383                  }
384              }
385#endif
386         
[15780]387          i++;
[14481]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{
[17073]992  XBell(gdk_display, 0);
[14481]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.