]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkmain-fb.c
Set the client ID on all displays. (#85713)
[~andy/gtk] / gdk / linux-fb / gdkmain-fb.c
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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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-2000.  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 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <sys/ioctl.h>
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <time.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/vt.h>
39 #include <sys/kd.h>
40 #include <errno.h>
41
42 #include <sys/socket.h>
43 #include <sys/un.h>
44
45 #include "gdk.h"
46
47 #include "gdkprivate-fb.h"
48 #include "gdkinternals.h"
49 #include "gdkfbmanager.h"
50
51 /* Private variable declarations
52  */
53 static int gdk_initialized = 0;                     /* 1 if the library is initialized,
54                                                      * 0 otherwise.
55                                                      */
56
57 #ifdef G_ENABLE_DEBUG
58 static const GDebugKey gdk_debug_keys[] = {
59   {"misc",          GDK_DEBUG_MISC},
60   {"events",        GDK_DEBUG_EVENTS},
61 };
62
63 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
64
65 #endif /* G_ENABLE_DEBUG */
66
67 GdkArgDesc _gdk_windowing_args[] = {
68   { NULL }
69 };
70
71 static const GScannerConfig     fb_modes_scanner_config =
72 {
73   (
74    " \t\n"
75    )                    /* cset_skip_characters */,
76   (
77    G_CSET_a_2_z
78    G_CSET_A_2_Z
79    )                    /* cset_identifier_first */,
80   (
81    G_CSET_a_2_z
82    "_-0123456789"
83    G_CSET_A_2_Z
84    )                    /* cset_identifier_nth */,
85   ( "#\n" )             /* cpair_comment_single */,
86   
87   FALSE                  /* case_sensitive */,
88   
89   FALSE                 /* skip_comment_multi */,
90   TRUE                  /* skip_comment_single */,
91   FALSE                 /* scan_comment_multi */,
92   TRUE                  /* scan_identifier */,
93   TRUE                  /* scan_identifier_1char */,
94   FALSE                 /* scan_identifier_NULL */,
95   TRUE                  /* scan_symbols */,
96   FALSE                 /* scan_binary */,
97   FALSE                 /* scan_octal */,
98   FALSE                  /* scan_float */,
99   FALSE                  /* scan_hex */,
100   FALSE                 /* scan_hex_dollar */,
101   FALSE                 /* scan_string_sq */,
102   TRUE                  /* scan_string_dq */,
103   TRUE                  /* numbers_2_int */,
104   FALSE                 /* int_2_float */,
105   FALSE                 /* identifier_2_string */,
106   TRUE                  /* char_2_token */,
107   FALSE                 /* symbol_2_token */,
108   FALSE                 /* scope_0_fallback */,
109 };
110
111 enum {
112   FB_MODE,
113   FB_ENDMODE,
114   FB_GEOMETRY,
115   FB_TIMINGS,
116   FB_LACED,
117   FB_HSYNC,
118   FB_VSYNC,
119   FB_CSYNC,
120   FB_EXTSYNC,
121   FB_DOUBLE,
122   FB_ACCEL
123 };
124
125 char *fb_modes_keywords[] =
126 {
127   "mode",
128   "endmode",
129   "geometry",
130   "timings",
131   "laced",
132   "hsync",
133   "vsync",
134   "csync",
135   "extsync",
136   "double",
137   "accel"
138 };
139
140 static int
141 fb_modes_parse_mode (GScanner *scanner,
142                      struct fb_var_screeninfo *modeinfo,
143                      char *specified_modename)
144 {
145   guint token;
146   int keyword;
147   int i;
148   char *modename;
149   int geometry[5];
150   int timings[7];
151   int vsync=0, hsync=0, csync=0, extsync=0, doublescan=0, laced=0, accel=1;
152   int found_geometry = 0;
153   int found_timings = 0;
154     
155   token = g_scanner_get_next_token (scanner);
156   if (token != G_TOKEN_SYMBOL)
157     return -1;
158   
159   keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
160   if (keyword != FB_MODE)
161     return -1;
162
163   token = g_scanner_get_next_token (scanner);
164   if (token != G_TOKEN_STRING)
165     return -1;
166
167   modename = g_strdup (scanner->value.v_string);
168   
169   token = g_scanner_get_next_token (scanner);
170   if (token != G_TOKEN_SYMBOL)
171     {
172       g_free (modename);
173       return -1; /* Not a valid keyword */
174     }
175   keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
176   while ( keyword != FB_ENDMODE )
177     {
178
179       switch (GPOINTER_TO_INT (scanner->value.v_symbol))
180         {
181         case FB_GEOMETRY:
182           for (i = 0; i < 5;i++) {
183             token = g_scanner_get_next_token (scanner);
184             if (token != G_TOKEN_INT)
185               {
186                 g_free (modename);
187                 return -1; /* need a integer */
188               }
189             geometry[i] = scanner->value.v_int;
190           }
191           found_geometry = TRUE;
192           break;
193         case FB_TIMINGS:
194           for (i = 0; i < 7; i++) {
195             token = g_scanner_get_next_token (scanner);
196             if (token != G_TOKEN_INT)
197               {
198                 g_free (modename);
199                 return -1; /* need a integer */
200               }
201             timings[i] = scanner->value.v_int;
202           }
203           found_timings = TRUE;
204           break;
205         case FB_LACED:
206           token = g_scanner_get_next_token (scanner);
207           if (token != G_TOKEN_IDENTIFIER)
208               {
209                 g_free (modename);
210                 return -1;
211               }
212           if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
213             laced = 1;
214           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
215             laced = 0;
216           else
217             {
218               g_free (modename);
219               return -1;
220             }
221           break;
222         case FB_EXTSYNC:
223           token = g_scanner_get_next_token (scanner);
224           if (token != G_TOKEN_IDENTIFIER)
225               {
226                 g_free (modename);
227                 return -1;
228               }
229           if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
230             extsync = 1;
231           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
232             extsync = 0;
233           else
234             {
235               g_free (modename);
236               return -1;
237             }
238           break;
239         case FB_DOUBLE:
240           token = g_scanner_get_next_token (scanner);
241           if (token != G_TOKEN_IDENTIFIER)
242               {
243                 g_free (modename);
244                 return -1;
245               }
246           if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
247             doublescan = 1;
248           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
249             doublescan = 0;
250           else
251             {
252               g_free (modename);
253               return -1;
254             }
255           break;
256         case FB_VSYNC:
257           token = g_scanner_get_next_token (scanner);
258           if (token != G_TOKEN_IDENTIFIER)
259               {
260                 g_free (modename);
261                 return -1;
262               }
263           if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
264             vsync = 1;
265           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
266             vsync = 0;
267           else
268             {
269               g_free (modename);
270               return -1;
271             }
272           break;
273         case FB_HSYNC:
274           token = g_scanner_get_next_token (scanner);
275           if (token != G_TOKEN_IDENTIFIER)
276             {
277               g_free (modename);
278               return -1;
279             }
280           if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
281             hsync = 1;
282           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
283             hsync = 0;
284           else
285             {
286               g_free (modename);
287               return -1;
288             }
289           break;
290         case FB_CSYNC:
291           token = g_scanner_get_next_token (scanner);
292           if (token != G_TOKEN_IDENTIFIER)
293             {
294               g_free (modename);
295               return -1;
296             }
297           if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
298             csync = 1;
299           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
300             csync = 0;
301           else
302             {
303               g_free (modename);
304               return -1;
305             }
306           break;
307         case FB_ACCEL:
308           token = g_scanner_get_next_token (scanner);
309           if (token != G_TOKEN_IDENTIFIER)
310             {
311               g_free (modename);
312               return -1;
313             }
314           if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
315             accel = 0;
316           else if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
317             accel = 1;
318           else
319             {
320               g_free (modename);
321               return -1;
322             }
323           break;
324         }
325       
326       token = g_scanner_get_next_token (scanner);
327       if (token != G_TOKEN_SYMBOL)
328         {
329           g_free (modename);
330           return -1; /* Not a valid keyword */
331         }
332       keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
333     }
334
335   if (strcmp (modename, specified_modename)== 0) {
336     if (!found_geometry)
337       g_warning ("Geometry not specified");
338
339     if (found_geometry)
340       {
341         modeinfo->xres = geometry[0];
342         modeinfo->yres = geometry[1];
343         modeinfo->xres_virtual = geometry[2];
344         modeinfo->yres_virtual = geometry[3];
345         modeinfo->bits_per_pixel = geometry[4];
346       }
347     
348     if (!found_timings)
349       g_warning ("Timing not specified");
350     
351     if (found_timings)
352       {
353         modeinfo->pixclock = timings[0];
354         modeinfo->left_margin = timings[1];
355         modeinfo->right_margin = timings[2];
356         modeinfo->upper_margin = timings[3];
357         modeinfo->lower_margin = timings[4];
358         modeinfo->hsync_len = timings[5];
359         modeinfo->vsync_len = timings[6];
360         
361         modeinfo->vmode = 0;
362         if (laced)
363           modeinfo->vmode |= FB_VMODE_INTERLACED;
364         if (doublescan)
365           modeinfo->vmode |= FB_VMODE_DOUBLE;
366           
367         modeinfo->sync = 0;
368         if (hsync)
369           modeinfo->sync |= FB_SYNC_HOR_HIGH_ACT;
370         if (vsync)
371           modeinfo->sync |= FB_SYNC_VERT_HIGH_ACT;
372         if (accel)
373           modeinfo->accel_flags = FB_ACCELF_TEXT;
374         else
375           modeinfo->accel_flags = 0;
376       }
377
378     g_free (modename);
379     return 1;
380   }
381   
382   g_free (modename);
383
384   return 0;
385 }
386
387 static int
388 gdk_fb_setup_mode_from_name (struct fb_var_screeninfo *modeinfo,
389                              char *modename)
390 {
391   GScanner *scanner;
392   char *filename;
393   gint result;
394   int fd, i;
395   int retval;
396
397   retval = 0;
398   
399   filename = "/etc/fb.modes";
400   
401   fd = open (filename, O_RDONLY);
402   if (fd < 0)
403     {
404       g_warning ("Cannot read %s", filename);
405       return retval;
406     }
407   
408   scanner = g_scanner_new ((GScannerConfig *) &fb_modes_scanner_config);
409   scanner->input_name = filename;
410
411   for (i = 0; i < sizeof(fb_modes_keywords)/sizeof(fb_modes_keywords[0]); i++)
412     g_scanner_add_symbol (scanner, fb_modes_keywords[i], GINT_TO_POINTER (i));
413
414   g_scanner_input_file (scanner, fd);
415   
416   while (1) {
417     if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF) {
418       break;
419     } 
420     result = fb_modes_parse_mode (scanner, modeinfo, modename);
421       
422     if (result < 0) {
423       g_warning ("parse error in %s at line %d", filename, scanner->line);
424       break;
425     }
426     if (result > 0)
427       {
428         retval = 1;
429         break;
430       }
431   }
432   
433   g_scanner_destroy (scanner);
434   
435   close (fd);
436   
437   return retval;
438 }
439   
440
441 static int
442 gdk_fb_set_mode (GdkFBDisplay *display)
443 {
444   char *env, *end;
445   int depth, height, width;
446   gboolean changed;
447   
448   if (ioctl (display->fb_fd, FBIOGET_VSCREENINFO, &display->modeinfo) < 0)
449     return -1;
450
451   display->orig_modeinfo = display->modeinfo;
452
453   changed = FALSE;
454   
455   env = getenv ("GDK_DISPLAY_MODE");
456   if (env)
457     {
458       if (gdk_fb_setup_mode_from_name (&display->modeinfo, env))
459         changed = TRUE;
460       else
461         g_warning ("Couldn't find mode named '%s'", env);
462     }
463
464   env = getenv ("GDK_DISPLAY_DEPTH");
465   if (env)
466     {
467       depth = strtol (env, &end, 10);
468       if (env != end)
469         {
470           changed = TRUE;
471           display->modeinfo.bits_per_pixel = depth;
472         }
473     }
474   
475   env = getenv ("GDK_DISPLAY_WIDTH");
476   if (env)
477     {
478       width = strtol (env, &end, 10);
479       if (env != end)
480         {
481           changed = TRUE;
482           display->modeinfo.xres = width;
483           display->modeinfo.xres_virtual = width;
484         }
485     }
486     
487   env = getenv ("GDK_DISPLAY_HEIGHT");
488   if (env)
489     {
490       height = strtol (env, &end, 10);
491       if (env != end)
492         {
493           changed = TRUE;
494           display->modeinfo.yres = height;
495           display->modeinfo.yres_virtual = height;
496         }
497     }
498
499   if (changed &&
500       (ioctl (display->fb_fd, FBIOPUT_VSCREENINFO, &display->modeinfo) < 0))
501     {
502       g_warning ("Couldn't set specified mode");
503       return -1;
504     }
505   
506   if (ioctl (display->fb_fd, FBIOGET_FSCREENINFO, &display->sinfo) < 0)
507     {
508       g_warning ("Error getting fixed screen info");
509       return -1;
510     }
511   return 0;
512 }
513
514 #ifdef ENABLE_FB_MANAGER
515 static void
516 gdk_fb_switch_from (void)
517 {
518   g_print ("Switch from\n");
519   gdk_shadow_fb_stop_updates ();
520   gdk_fb_mouse_close ();
521   gdk_fb_keyboard_close ();
522 }
523
524 static void
525 gdk_fb_switch_to (void)
526 {
527   g_print ("switch_to\n");
528   gdk_shadow_fb_update (0, 0, 
529                         gdk_display->fb_width, 
530                         gdk_display->fb_height);
531
532   if (!gdk_fb_keyboard_open ())
533     g_warning ("Failed to re-initialize keyboard");
534   
535   if (!gdk_fb_mouse_open ())
536     g_warning ("Failed to re-initialize mouse");
537
538 }
539
540
541 static gboolean
542 gdk_fb_manager_callback (GIOChannel *gioc,
543                          GIOCondition cond,
544                          gpointer data)
545 {
546   struct FBManagerMessage msg;
547   GdkFBDisplay *display;
548   int res;
549
550   display = data;
551
552   res = recv (display->manager_fd, &msg, sizeof (msg), 0);
553
554   if (res==0)
555     {
556       g_source_remove (gdk_display->manager_tag);
557       /*g_io_channel_unref (kb->io);*/
558       close (gdk_display->manager_fd);
559
560     }
561
562   if (res != sizeof (msg))
563     {
564       g_warning ("Got wrong size message");
565       return TRUE;
566     }
567   
568   switch (msg.msg_type)
569     {
570     case FB_MANAGER_SWITCH_FROM:
571       g_print ("Got switch from message\n");
572       display->manager_blocked = TRUE;
573       gdk_fb_switch_from ();
574       msg.msg_type = FB_MANAGER_ACK;
575       send (display->manager_fd, &msg, sizeof (msg), 0);
576       break;
577     case FB_MANAGER_SWITCH_TO:
578       g_print ("Got switch to message\n");
579       display->manager_blocked = FALSE;
580       gdk_fb_switch_to ();
581       break;
582     default:
583       g_warning ("Got unknown message");
584     }
585   return TRUE;
586 }
587
588 #endif /* ENABLE_FB_MANAGER */
589
590 static void
591 gdk_fb_manager_connect (GdkFBDisplay *display)
592 {
593 #ifdef ENABLE_FB_MANAGER
594   int fd;
595   struct sockaddr_un addr;
596   struct msghdr msg = {0};
597   struct cmsghdr *cmsg;
598   struct ucred credentials;
599   struct FBManagerMessage init_msg;
600   struct iovec iov;
601   char buf[CMSG_SPACE (sizeof (credentials))];  /* ancillary data buffer */
602   int *fdptr;
603   int res;
604
605   display->manager_blocked = FALSE;
606   display->manager_fd = -1;
607
608   fd = socket (PF_UNIX, SOCK_STREAM, 0);
609   
610   g_print ("socket: %d\n", fd);
611
612   if (fd < 0)
613     return;
614
615   addr.sun_family = AF_UNIX;
616   strcpy (addr.sun_path, "/tmp/.fb.manager");
617
618   if (connect(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0) 
619     {
620       g_print ("connect failed\n");
621       close (fd);
622       return;
623     }
624   
625   credentials.pid = getpid ();
626   credentials.uid = geteuid ();
627   credentials.gid = getegid ();
628
629   init_msg.msg_type = FB_MANAGER_NEW_CLIENT;
630   iov.iov_base = &init_msg;
631   iov.iov_len = sizeof (init_msg);
632
633   msg.msg_name = NULL;
634   msg.msg_namelen = 0;
635   msg.msg_iov = &iov;
636   msg.msg_iovlen = 1;
637   msg.msg_control = buf;
638   msg.msg_controllen = sizeof buf;
639   cmsg = CMSG_FIRSTHDR(&msg);
640   cmsg->cmsg_level = SOL_SOCKET;
641   cmsg->cmsg_type = SCM_CREDENTIALS;
642   cmsg->cmsg_len = CMSG_LEN (sizeof (credentials));
643   /* Initialize the payload: */
644   fdptr = (int *)CMSG_DATA (cmsg);
645   memcpy (fdptr, &credentials, sizeof (credentials));
646   /* Sum of the length of all control messages in the buffer: */
647   msg.msg_controllen = cmsg->cmsg_len;
648
649   res = sendmsg (fd, &msg, 0);
650
651   display->manager_fd = fd;
652   display->manager_blocked = TRUE;
653
654   display->manager_tag = g_io_add_watch (g_io_channel_unix_new (fd),
655                                          G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
656                                          gdk_fb_manager_callback,
657                                          display);
658
659   init_msg.msg_type = FB_MANAGER_REQUEST_SWITCH_TO_PID;
660   init_msg.data = getpid ();
661
662   /* Request a switch-to */
663   send (fd, &init_msg, sizeof (init_msg), 0);
664 #endif
665 }
666
667 static GdkFBDisplay *
668 gdk_fb_display_new ()
669 {
670   GdkFBDisplay *display;
671   gchar *fb_filename;
672   struct vt_stat vs;
673   int vt, n;
674   gchar *s, *send;
675   char buf[32];
676
677   display = g_new0 (GdkFBDisplay, 1);
678
679   display->console_fd = open ("/dev/console", O_RDWR);
680   if (display->console_fd < 0)
681     {
682       g_warning ("Can't open /dev/console: %s", strerror (errno));
683       g_free (display);
684       return NULL;
685     }
686   
687   ioctl (display->console_fd, VT_GETSTATE, &vs);
688   display->start_vt = vs.v_active;
689
690   vt = display->start_vt;
691   s = getenv("GDK_VT");
692   if (s)
693     {
694       if (g_ascii_strcasecmp ("new", s)==0)
695         {
696           n = ioctl (display->console_fd, VT_OPENQRY, &vt);
697           if (n < 0 || vt == -1)
698             g_error("Cannot allocate new VT");
699         }
700       else
701         {
702           vt = strtol (s, &send, 10);
703           if (s==send)
704             {
705               g_warning ("Cannot parse GDK_VT");
706               vt = display->start_vt;
707             }
708         }
709       
710     }
711
712   display->vt = vt;
713   
714   /* Switch to the new VT */
715   if (vt != display->start_vt)
716     {
717       ioctl (display->console_fd, VT_ACTIVATE, vt);
718       ioctl (display->console_fd, VT_WAITACTIVE, vt);
719     }
720   
721   /* Open the tty */
722   g_snprintf (buf, sizeof(buf), "/dev/tty%d", vt);
723   display->tty_fd = open (buf, O_RDWR|O_NONBLOCK);
724   if (display->tty_fd < 0)
725     {
726       g_warning ("Can't open %s: %s", buf, strerror (errno));
727       close (display->console_fd);
728       g_free (display);
729       return NULL;
730     }
731
732   /* Set controlling tty */
733   ioctl (0, TIOCNOTTY, 0);
734   ioctl (display->tty_fd, TIOCSCTTY, 0);
735   
736   fb_filename = gdk_get_display ();
737   display->fb_fd = open (fb_filename, O_RDWR);
738   if (display->fb_fd < 0)
739     {
740       g_warning ("Can't open %s: %s", fb_filename, strerror (errno));
741       g_free (fb_filename);
742       close (display->tty_fd);
743       close (display->console_fd);
744       g_free (display);
745       return NULL;
746     }
747   g_free (fb_filename);
748
749   if (gdk_fb_set_mode (display) < 0)
750     {
751       close (display->fb_fd);
752       close (display->tty_fd);
753       close (display->console_fd);
754       g_free (display);
755       return NULL;
756     }
757
758   /* Disable normal text on the console */
759   ioctl (display->fb_fd, KDSETMODE, KD_GRAPHICS);
760
761   ioctl (display->fb_fd, FBIOBLANK, 0);
762
763   /* We used to use sinfo.smem_len, but that seemed to be broken in many cases */
764   display->fb_mmap = mmap (NULL,
765                            display->modeinfo.yres * display->sinfo.line_length,
766                            PROT_READ|PROT_WRITE,
767                            MAP_SHARED,
768                            display->fb_fd,
769                            0);
770   g_assert (display->fb_mmap != MAP_FAILED);
771
772   if (display->sinfo.visual == FB_VISUAL_TRUECOLOR)
773     {
774       display->red_byte = display->modeinfo.red.offset >> 3;
775       display->green_byte = display->modeinfo.green.offset >> 3;
776       display->blue_byte = display->modeinfo.blue.offset >> 3;
777     }
778
779 #ifdef ENABLE_SHADOW_FB
780   if (_gdk_fb_screen_angle % 2 == 0)
781     {
782       display->fb_width = display->modeinfo.xres;
783       display->fb_height = display->modeinfo.yres;
784     } 
785   else
786     {
787       display->fb_width = display->modeinfo.yres;
788       display->fb_height = display->modeinfo.xres;
789     }
790   display->fb_stride =
791     display->fb_width * (display->modeinfo.bits_per_pixel / 8);
792   display->fb_mem = g_malloc(display->fb_height * display->fb_stride);
793 #else
794   display->fb_mem = display->fb_mmap;
795   display->fb_width = display->modeinfo.xres;
796   display->fb_height = display->modeinfo.yres;
797   display->fb_stride = display->sinfo.line_length;
798 #endif
799
800   return display;
801 }
802
803 static void
804 gdk_fb_display_destroy (GdkFBDisplay *display)
805 {
806   /* Restore old framebuffer mode */
807   ioctl (display->fb_fd, FBIOPUT_VSCREENINFO, &display->orig_modeinfo);
808   
809   /* Enable normal text on the console */
810   ioctl (display->fb_fd, KDSETMODE, KD_TEXT);
811   
812   munmap (display->fb_mmap, display->modeinfo.yres * display->sinfo.line_length);
813   close (display->fb_fd);
814
815   ioctl (display->console_fd, VT_ACTIVATE, display->start_vt);
816   ioctl (display->console_fd, VT_WAITACTIVE, display->start_vt);
817   if (display->vt != display->start_vt)
818     ioctl (display->console_fd, VT_DISALLOCATE, display->vt);
819   
820   close (display->tty_fd);
821   close (display->console_fd);
822   g_free (display);
823 }
824
825 void
826 _gdk_windowing_init (int *argc, char ***argv)
827 {
828   if (gdk_initialized)
829     return;
830
831   /* Create new session and become session leader */
832   setsid();
833
834   gdk_display = gdk_fb_display_new ();
835
836   if (!gdk_display)
837     return;
838
839   gdk_shadow_fb_init ();
840   
841   gdk_fb_manager_connect (gdk_display);
842
843   if (!gdk_fb_keyboard_init (!gdk_display->manager_blocked))
844     {
845       g_warning ("Failed to initialize keyboard");
846       gdk_fb_display_destroy (gdk_display);
847       gdk_display = NULL;
848       return;
849     }
850   
851   if (!gdk_fb_mouse_init (!gdk_display->manager_blocked))
852     {
853       g_warning ("Failed to initialize mouse");
854       gdk_fb_keyboard_close ();
855       gdk_fb_display_destroy (gdk_display);
856       gdk_display = NULL;
857       return;
858     }
859
860   /* Although atexit is evil, we need it here because otherwise the
861    * keyboard is left in a bad state. you can still run 'reset' but
862    * that gets annoying after running testgtk for the 20th time.
863    */
864   g_atexit(_gdk_windowing_exit);
865
866   gdk_initialized = TRUE;
867
868   _gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
869
870 }
871
872 void
873 _gdk_windowing_set_default_display (GdkDisplay *display)
874 {
875 }
876
877 /*
878  *--------------------------------------------------------------
879  * gdk_pointer_grab
880  *
881  *   Grabs the pointer to a specific window
882  *
883  * Arguments:
884  *   "window" is the window which will receive the grab
885  *   "owner_events" specifies whether events will be reported as is,
886  *     or relative to "window"
887  *   "event_mask" masks only interesting events
888  *   "confine_to" limits the cursor movement to the specified window
889  *   "cursor" changes the cursor for the duration of the grab
890  *   "time" specifies the time
891  *
892  * Results:
893  *
894  * Side effects:
895  *   requires a corresponding call to gdk_pointer_ungrab
896  *
897  *--------------------------------------------------------------
898  */
899
900 GdkGrabStatus
901 gdk_pointer_grab (GdkWindow *     window,
902                   gint            owner_events,
903                   GdkEventMask    event_mask,
904                   GdkWindow *     confine_to,
905                   GdkCursor *     cursor,
906                   guint32         time)
907 {
908   return gdk_fb_pointer_grab (window,
909                               owner_events,
910                               event_mask,
911                               confine_to,
912                               cursor,
913                               time, FALSE);
914 }
915
916 static gboolean _gdk_fb_pointer_implicit_grab = FALSE;
917
918 GdkGrabStatus
919 gdk_fb_pointer_grab (GdkWindow *          window,
920                      gint                 owner_events,
921                      GdkEventMask         event_mask,
922                      GdkWindow *          confine_to,
923                      GdkCursor *          cursor,
924                      guint32              time,
925                      gboolean             implicit_grab)
926 {
927   g_return_val_if_fail (window != NULL, 0);
928   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
929   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
930
931   if (_gdk_fb_pointer_grab_window)
932     {
933       if (implicit_grab && !_gdk_fb_pointer_implicit_grab)
934         return GDK_GRAB_ALREADY_GRABBED;
935
936       gdk_pointer_ungrab (time);
937     }
938
939   gdk_fb_window_send_crossing_events (NULL,
940                                       window,
941                                       GDK_CROSSING_GRAB);  
942
943   if (event_mask & GDK_BUTTON_MOTION_MASK)
944       event_mask |=
945         GDK_BUTTON1_MOTION_MASK |
946         GDK_BUTTON2_MOTION_MASK |
947         GDK_BUTTON3_MOTION_MASK;
948   
949   _gdk_fb_pointer_implicit_grab = implicit_grab;
950
951   _gdk_fb_pointer_grab_window = gdk_window_ref (window);
952   _gdk_fb_pointer_grab_owner_events = owner_events;
953
954   _gdk_fb_pointer_grab_confine = confine_to ? gdk_window_ref (confine_to) : NULL;
955   _gdk_fb_pointer_grab_events = event_mask;
956   _gdk_fb_pointer_grab_cursor = cursor ? gdk_cursor_ref (cursor) : NULL;
957
958
959   
960   if (cursor)
961     gdk_fb_cursor_reset ();
962
963   return GDK_GRAB_SUCCESS;
964 }
965
966 /*
967  *--------------------------------------------------------------
968  * gdk_display_pointer_ungrab
969  *
970  *   Releases any pointer grab
971  *
972  * Arguments:
973  *
974  * Results:
975  *
976  * Side effects:
977  *
978  *--------------------------------------------------------------
979  */
980
981 void
982 gdk_display_pointer_ungrab (GdkDisplay *display,
983                             guint32     time)
984 {
985   gdk_fb_pointer_ungrab (time, FALSE);
986 }
987
988 void
989 gdk_fb_pointer_ungrab (guint32 time, gboolean implicit_grab)
990 {
991   gboolean have_grab_cursor = _gdk_fb_pointer_grab_cursor && 1;
992   GdkWindow *mousewin;
993   GdkWindow *old_grab_window;
994   
995   if (!_gdk_fb_pointer_grab_window)
996     return;
997
998   if (implicit_grab && !_gdk_fb_pointer_implicit_grab)
999     return;
1000
1001   if (_gdk_fb_pointer_grab_confine)
1002     gdk_window_unref (_gdk_fb_pointer_grab_confine);
1003   _gdk_fb_pointer_grab_confine = NULL;
1004
1005   if (_gdk_fb_pointer_grab_cursor)
1006     gdk_cursor_unref (_gdk_fb_pointer_grab_cursor);
1007   _gdk_fb_pointer_grab_cursor = NULL;
1008
1009   if (have_grab_cursor)
1010     gdk_fb_cursor_reset ();
1011
1012   old_grab_window = _gdk_fb_pointer_grab_window;
1013   
1014   _gdk_fb_pointer_grab_window = NULL;
1015
1016   _gdk_fb_pointer_implicit_grab = FALSE;
1017
1018   mousewin = gdk_window_at_pointer (NULL, NULL);
1019   gdk_fb_window_send_crossing_events (old_grab_window,
1020                                       mousewin,
1021                                       GDK_CROSSING_UNGRAB);
1022   
1023   if (old_grab_window)
1024     gdk_window_unref (old_grab_window);
1025 }
1026
1027 /*
1028  *--------------------------------------------------------------
1029  * gdk_display_pointer_is_grabbed
1030  *
1031  *   Tell wether there is an active x pointer grab in effect
1032  *
1033  * Arguments:
1034  *
1035  * Results:
1036  *
1037  * Side effects:
1038  *
1039  *--------------------------------------------------------------
1040  */
1041
1042 gint
1043 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1044 {
1045   return _gdk_fb_pointer_grab_window != NULL;
1046 }
1047
1048 /*
1049  *--------------------------------------------------------------
1050  * gdk_keyboard_grab
1051  *
1052  *   Grabs the keyboard to a specific window
1053  *
1054  * Arguments:
1055  *   "window" is the window which will receive the grab
1056  *   "owner_events" specifies whether events will be reported as is,
1057  *     or relative to "window"
1058  *   "time" specifies the time
1059  *
1060  * Results:
1061  *
1062  * Side effects:
1063  *   requires a corresponding call to gdk_keyboard_ungrab
1064  *
1065  *--------------------------------------------------------------
1066  */
1067
1068 GdkGrabStatus
1069 gdk_keyboard_grab (GdkWindow  *window,
1070                    gint        owner_events,
1071                    guint32     time)
1072 {
1073   g_return_val_if_fail (window != NULL, 0);
1074   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1075
1076   if (_gdk_fb_pointer_grab_window)
1077     gdk_keyboard_ungrab (time);
1078
1079   _gdk_fb_keyboard_grab_window = gdk_window_ref (window);
1080   _gdk_fb_keyboard_grab_owner_events = owner_events;
1081   
1082   return GDK_GRAB_SUCCESS;
1083 }
1084
1085 /*
1086  *--------------------------------------------------------------
1087  * gdk_display_keyboard_ungrab
1088  *
1089  *   Releases any keyboard grab
1090  *
1091  * Arguments:
1092  *
1093  * Results:
1094  *
1095  * Side effects:
1096  *
1097  *--------------------------------------------------------------
1098  */
1099
1100 void
1101 gdk_display_keyboard_ungrab (GdkDisplay *display,
1102                              guint32     time)
1103 {
1104   if (_gdk_fb_keyboard_grab_window)
1105     gdk_window_unref (_gdk_fb_keyboard_grab_window);
1106   _gdk_fb_keyboard_grab_window = NULL;
1107 }
1108
1109 gboolean
1110 gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1111                                    GdkWindow **grab_window,
1112                                    gboolean   *owner_events)
1113 {
1114   if (_gdk_fb_pointer_grab_window)
1115     {
1116       if (grab_window)
1117         *grab_window = (GdkWindow *)_gdk_fb_pointer_grab_window;
1118       if (owner_events)
1119         *owner_events = _gdk_fb_pointer_grab_owner_events;
1120       
1121       return TRUE;
1122     }
1123   else
1124     return FALSE;
1125 }
1126
1127 gboolean
1128 gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1129                                     GdkWindow **grab_window,
1130                                     gboolean   *owner_events)
1131 {
1132   if (_gdk_fb_keyboard_grab_window)
1133     {
1134       if (grab_window)
1135         *grab_window = (GdkWindow *)_gdk_fb_keyboard_grab_window;
1136       if (owner_events)
1137         *owner_events = _gdk_fb_keyboard_grab_owner_events;
1138
1139       return TRUE;
1140     }
1141   else
1142     return FALSE;
1143 }
1144
1145
1146 /*
1147  *--------------------------------------------------------------
1148  * gdk_screen_get_width
1149  *
1150  *   Return the width of the screen.
1151  *
1152  * Arguments:
1153  *
1154  * Results:
1155  *
1156  * Side effects:
1157  *
1158  *--------------------------------------------------------------
1159  */
1160
1161 gint
1162 gdk_screen_get_width (GdkScreen *screen)
1163 {
1164   return gdk_display->fb_width;
1165 }
1166
1167 /*
1168  *--------------------------------------------------------------
1169  * gdk_screen_get_height
1170  *
1171  *   Return the height of the screen.
1172  *
1173  * Arguments:
1174  *
1175  * Results:
1176  *
1177  * Side effects:
1178  *
1179  *--------------------------------------------------------------
1180  */
1181
1182 gint
1183 gdk_screen_get_height (GdkScreen *screen)
1184 {
1185   return gdk_display->fb_height;
1186 }
1187
1188 /*
1189  *--------------------------------------------------------------
1190  * gdk_screen_get_width_mm
1191  *
1192  *   Return the width of the screen in millimeters.
1193  *
1194  * Arguments:
1195  *
1196  * Results:
1197  *
1198  * Side effects:
1199  *
1200  *--------------------------------------------------------------
1201  */
1202
1203 gint
1204 gdk_screen_get_width_mm (GdkScreen *screen)
1205 {
1206   return 0.5 + gdk_screen_width () * (25.4 / 72.);
1207 }
1208
1209 /*
1210  *--------------------------------------------------------------
1211  * gdk_screen_get_height_mm
1212  *
1213  *   Return the height of the screen in millimeters.
1214  *
1215  * Arguments:
1216  *
1217  * Results:
1218  *
1219  * Side effects:
1220  *
1221  *--------------------------------------------------------------
1222  */
1223
1224 gint
1225 gdk_screen_get_height_mm (GdkScreen *screen)
1226 {
1227   return 0.5 + gdk_screen_height () * (25.4 / 72.);
1228 }
1229
1230 void
1231 _gdk_windowing_display_set_sm_client_id (GdkDisplay*  display,
1232                                          const gchar* sm_client_id)
1233 {
1234 }
1235
1236 extern void keyboard_shutdown(void);
1237
1238 void
1239 _gdk_windowing_exit (void)
1240 {
1241
1242   gdk_fb_mouse_close ();
1243   /*leak  g_free (gdk_fb_mouse);*/
1244   
1245   gdk_fb_keyboard_close ();
1246   /*leak g_free (gdk_fb_keyboard);*/
1247   
1248   gdk_fb_display_destroy (gdk_display);
1249   
1250   gdk_display = NULL;
1251 }
1252
1253 gchar *
1254 gdk_get_display(void)
1255 {
1256   gchar *s;
1257
1258   s = getenv ("GDK_DISPLAY");
1259   if (s==0)
1260     s = "/dev/fb0";
1261   
1262   return g_strdup (s);
1263 }
1264
1265 void
1266 gdk_display_beep (GdkDisplay *display)
1267 {
1268   static int pitch = 600, duration = 100;
1269   gulong arg;
1270
1271   /* Thank you XFree86 */
1272   arg = ((1193190 / pitch) & 0xffff) |
1273     (((unsigned long)duration) << 16);
1274
1275   ioctl (gdk_display->tty_fd, KDMKTONE, arg);
1276 }
1277
1278 /* utils */
1279 static const guint type_masks[] = {
1280   GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE          = 0, */
1281   GDK_STRUCTURE_MASK, /* GDK_DESTROY            = 1, */
1282   GDK_EXPOSURE_MASK, /* GDK_EXPOSE              = 2, */
1283   GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3, */
1284   GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS    = 4, */
1285   GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS   = 5, */
1286   GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS   = 6, */
1287   GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE        = 7, */
1288   GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS  = 8, */
1289   GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE      = 9, */
1290   GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY    = 10, */
1291   GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY    = 11, */
1292   GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE    = 12, */
1293   GDK_STRUCTURE_MASK, /* GDK_CONFIGURE          = 13, */
1294   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP                = 14, */
1295   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP              = 15, */
1296   GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY      = 16, */
1297   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR      = 17, */
1298   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18, */
1299   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY     = 19, */
1300   GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN    = 20, */
1301   GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT  = 21, */
1302   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER        = 22, */
1303   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE        = 23, */
1304   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION       = 24, */
1305   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS       = 25, */
1306   GDK_ALL_EVENTS_MASK, /* GDK_DROP_START        = 26, */
1307   GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED     = 27, */
1308   GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT      = 28, */
1309   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29, */
1310   GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE           = 30, */
1311   GDK_SCROLL_MASK /* GDK_SCROLL            = 31 */
1312 };
1313
1314 GdkWindow *
1315 gdk_fb_other_event_window (GdkWindow *window,
1316                            GdkEventType type)
1317 {
1318   guint32 evmask;
1319   GdkWindow *w;
1320
1321   w = window;
1322   while (w != _gdk_parent_root)
1323     {
1324       /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1325       if ((w != window) &&
1326           (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1327           (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1328           break;
1329           
1330       evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1331
1332       if (evmask & type_masks[type])
1333         return w;
1334       
1335       w = gdk_window_get_parent (w);
1336     }
1337   
1338   return NULL;
1339 }
1340
1341 GdkWindow *
1342 gdk_fb_pointer_event_window (GdkWindow *window,
1343                              GdkEventType type)
1344 {
1345   guint evmask;
1346   GdkModifierType mask;
1347   GdkWindow *w;
1348           
1349   gdk_fb_mouse_get_info (NULL, NULL, &mask);
1350   
1351   if (_gdk_fb_pointer_grab_window &&
1352       !_gdk_fb_pointer_grab_owner_events)
1353     {
1354       evmask = _gdk_fb_pointer_grab_events;
1355
1356       if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1357         {
1358           if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1359               ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1360               ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1361             evmask |= GDK_POINTER_MOTION_MASK;
1362         }
1363
1364       if (evmask & type_masks[type])
1365         return _gdk_fb_pointer_grab_window;
1366       else
1367         return NULL;
1368     }
1369
1370   w = window;
1371   while (w != _gdk_parent_root)
1372     {
1373       /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1374       if ((w != window) &&
1375           (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1376           (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1377           break;
1378       
1379       evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1380
1381       if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1382         {
1383           if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1384               ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1385               ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1386             evmask |= GDK_POINTER_MOTION_MASK;
1387         }
1388
1389       if (evmask & type_masks[type])
1390         return w;
1391       
1392       w = gdk_window_get_parent (w);
1393     }
1394
1395   if (_gdk_fb_pointer_grab_window &&
1396       _gdk_fb_pointer_grab_owner_events)
1397     {
1398       evmask = _gdk_fb_pointer_grab_events;
1399       
1400       if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1401         {
1402           if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1403               ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1404               ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1405             evmask |= GDK_POINTER_MOTION_MASK;
1406         }
1407       
1408       if (evmask & type_masks[type])
1409         return _gdk_fb_pointer_grab_window;
1410     }
1411   
1412   return NULL;
1413 }
1414
1415 GdkWindow *
1416 gdk_fb_keyboard_event_window (GdkWindow *window,
1417                               GdkEventType type)
1418 {
1419   guint32 evmask;
1420   GdkWindow *w;
1421   
1422   if (_gdk_fb_keyboard_grab_window &&
1423       !_gdk_fb_keyboard_grab_owner_events)
1424     {
1425       return _gdk_fb_keyboard_grab_window;
1426     }
1427   
1428   w = window;
1429   while (w != _gdk_parent_root)
1430     {
1431       /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1432       if ((w != window) &&
1433           (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1434           (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1435           break;
1436           
1437       evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1438
1439       if (evmask & type_masks[type])
1440         return w;
1441       
1442       w = gdk_window_get_parent (w);
1443     }
1444   
1445   if (_gdk_fb_keyboard_grab_window &&
1446       _gdk_fb_keyboard_grab_owner_events)
1447     {
1448       return _gdk_fb_keyboard_grab_window;
1449     }
1450
1451   return NULL;
1452 }
1453
1454 GdkEvent *
1455 gdk_event_make (GdkWindow *window,
1456                 GdkEventType type,
1457                 gboolean append_to_queue)
1458 {
1459   GdkEvent *event = _gdk_event_new ();
1460   guint32 the_time;
1461   
1462   the_time = gdk_fb_get_time ();
1463   
1464   event->any.type = type;
1465   event->any.window = gdk_window_ref (window);
1466   event->any.send_event = FALSE;
1467   switch (type)
1468     {
1469     case GDK_MOTION_NOTIFY:
1470       event->motion.time = the_time;
1471       event->motion.axes = NULL;
1472       break;
1473     case GDK_BUTTON_PRESS:
1474     case GDK_2BUTTON_PRESS:
1475     case GDK_3BUTTON_PRESS:
1476     case GDK_BUTTON_RELEASE:
1477       event->button.time = the_time;
1478       event->button.axes = NULL;
1479       break;
1480     case GDK_KEY_PRESS:
1481     case GDK_KEY_RELEASE:
1482       event->key.time = the_time;
1483       break;
1484     case GDK_ENTER_NOTIFY:
1485     case GDK_LEAVE_NOTIFY:
1486       event->crossing.time = the_time;
1487       break;
1488       
1489     case GDK_PROPERTY_NOTIFY:
1490       event->property.time = the_time;
1491       break;
1492       
1493     case GDK_SELECTION_CLEAR:
1494     case GDK_SELECTION_REQUEST:
1495     case GDK_SELECTION_NOTIFY:
1496       event->selection.time = the_time;
1497       break;
1498     case GDK_PROXIMITY_IN:
1499     case GDK_PROXIMITY_OUT:
1500       event->proximity.time = the_time;
1501       break;
1502     case GDK_DRAG_ENTER:
1503     case GDK_DRAG_LEAVE:
1504     case GDK_DRAG_MOTION:
1505     case GDK_DRAG_STATUS:
1506     case GDK_DROP_START:
1507     case GDK_DROP_FINISHED:
1508       event->dnd.time = the_time;
1509       break;
1510       
1511     case GDK_FOCUS_CHANGE:
1512     case GDK_CONFIGURE:
1513     case GDK_MAP:
1514     case GDK_UNMAP:
1515     case GDK_CLIENT_EVENT:
1516     case GDK_VISIBILITY_NOTIFY:
1517     case GDK_NO_EXPOSE:
1518     case GDK_SCROLL:
1519     case GDK_DELETE:
1520     case GDK_DESTROY:
1521     case GDK_EXPOSE:
1522     default:
1523       break;
1524     }
1525   
1526   if (append_to_queue)
1527     _gdk_event_queue_append (gdk_display_get_default (), event);
1528   
1529   return event;
1530 }
1531
1532 void
1533 gdk_fb_set_rotation (GdkFBAngle angle)
1534 {
1535   if (angle == _gdk_fb_screen_angle)
1536     return;
1537   
1538 #ifdef ENABLE_SHADOW_FB
1539   if (gdk_display)
1540     {
1541       gdk_shadow_fb_stop_updates ();
1542
1543       gdk_fb_cursor_hide ();
1544       
1545       _gdk_fb_screen_angle = angle;
1546
1547       if (angle % 2 == 0)
1548         {
1549           gdk_display->fb_width = gdk_display->modeinfo.xres;
1550           gdk_display->fb_height = gdk_display->modeinfo.yres;
1551         } 
1552       else
1553         {
1554           gdk_display->fb_width = gdk_display->modeinfo.yres;
1555           gdk_display->fb_height = gdk_display->modeinfo.xres;
1556         }
1557       gdk_display->fb_stride =
1558         gdk_display->fb_width * (gdk_display->modeinfo.bits_per_pixel / 8);
1559       
1560       gdk_fb_recompute_all();
1561       gdk_fb_redraw_all ();
1562       
1563       gdk_fb_cursor_unhide ();
1564     }
1565   else
1566     _gdk_fb_screen_angle = angle;
1567 #else
1568   g_warning ("Screen rotation without shadow fb not supported.");
1569 #endif
1570 }
1571
1572 void
1573 gdk_error_trap_push (void)
1574 {
1575 }
1576
1577 gint
1578 gdk_error_trap_pop (void)
1579 {
1580   return 0;
1581 }