1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
30 #include <sys/types.h>
32 #include <sys/ioctl.h>
43 #include <sys/socket.h>
48 #include "gdkprivate-fb.h"
49 #include "gdkinternals.h"
50 #include "gdkfbmanager.h"
52 /* Private variable declarations
54 static int gdk_initialized = 0; /* 1 if the library is initialized,
59 static const GDebugKey gdk_debug_keys[] = {
60 {"misc", GDK_DEBUG_MISC},
61 {"events", GDK_DEBUG_EVENTS},
64 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
66 #endif /* G_ENABLE_DEBUG */
68 GdkArgDesc _gdk_windowing_args[] = {
72 static const GScannerConfig fb_modes_scanner_config =
76 ) /* cset_skip_characters */,
80 ) /* cset_identifier_first */,
85 ) /* cset_identifier_nth */,
86 ( "#\n" ) /* cpair_comment_single */,
88 FALSE /* case_sensitive */,
90 FALSE /* skip_comment_multi */,
91 TRUE /* skip_comment_single */,
92 FALSE /* scan_comment_multi */,
93 TRUE /* scan_identifier */,
94 TRUE /* scan_identifier_1char */,
95 FALSE /* scan_identifier_NULL */,
96 TRUE /* scan_symbols */,
97 FALSE /* scan_binary */,
98 FALSE /* scan_octal */,
99 FALSE /* scan_float */,
100 FALSE /* scan_hex */,
101 FALSE /* scan_hex_dollar */,
102 FALSE /* scan_string_sq */,
103 TRUE /* scan_string_dq */,
104 TRUE /* numbers_2_int */,
105 FALSE /* int_2_float */,
106 FALSE /* identifier_2_string */,
107 TRUE /* char_2_token */,
108 FALSE /* symbol_2_token */,
109 FALSE /* scope_0_fallback */,
126 char *fb_modes_keywords[] =
142 fb_modes_parse_mode (GScanner *scanner,
143 struct fb_var_screeninfo *modeinfo,
144 char *specified_modename)
152 int vsync=0, hsync=0, csync=0, extsync=0, doublescan=0, laced=0, accel=1;
153 int found_geometry = 0;
154 int found_timings = 0;
156 token = g_scanner_get_next_token (scanner);
157 if (token != G_TOKEN_SYMBOL)
160 keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
161 if (keyword != FB_MODE)
164 token = g_scanner_get_next_token (scanner);
165 if (token != G_TOKEN_STRING)
168 modename = g_strdup (scanner->value.v_string);
170 token = g_scanner_get_next_token (scanner);
171 if (token != G_TOKEN_SYMBOL)
174 return -1; /* Not a valid keyword */
176 keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
177 while ( keyword != FB_ENDMODE )
180 switch (GPOINTER_TO_INT (scanner->value.v_symbol))
183 for (i = 0; i < 5;i++) {
184 token = g_scanner_get_next_token (scanner);
185 if (token != G_TOKEN_INT)
188 return -1; /* need a integer */
190 geometry[i] = scanner->value.v_int;
192 found_geometry = TRUE;
195 for (i = 0; i < 7; i++) {
196 token = g_scanner_get_next_token (scanner);
197 if (token != G_TOKEN_INT)
200 return -1; /* need a integer */
202 timings[i] = scanner->value.v_int;
204 found_timings = TRUE;
207 token = g_scanner_get_next_token (scanner);
208 if (token != G_TOKEN_IDENTIFIER)
213 if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
215 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
224 token = g_scanner_get_next_token (scanner);
225 if (token != G_TOKEN_IDENTIFIER)
230 if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
232 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
241 token = g_scanner_get_next_token (scanner);
242 if (token != G_TOKEN_IDENTIFIER)
247 if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
249 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
258 token = g_scanner_get_next_token (scanner);
259 if (token != G_TOKEN_IDENTIFIER)
264 if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
266 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
275 token = g_scanner_get_next_token (scanner);
276 if (token != G_TOKEN_IDENTIFIER)
281 if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
283 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
292 token = g_scanner_get_next_token (scanner);
293 if (token != G_TOKEN_IDENTIFIER)
298 if (g_ascii_strcasecmp (scanner->value.v_identifier, "high")==0)
300 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "low")==0)
309 token = g_scanner_get_next_token (scanner);
310 if (token != G_TOKEN_IDENTIFIER)
315 if (g_ascii_strcasecmp (scanner->value.v_identifier, "false")==0)
317 else if (g_ascii_strcasecmp (scanner->value.v_identifier, "true")==0)
327 token = g_scanner_get_next_token (scanner);
328 if (token != G_TOKEN_SYMBOL)
331 return -1; /* Not a valid keyword */
333 keyword = GPOINTER_TO_INT (scanner->value.v_symbol);
336 if (strcmp (modename, specified_modename)== 0) {
337 /* we really should be parsing for rgba. regardless, if rgba isn't found,
338 * we can't assume that the original colors are valid for the new mode */
339 memset (&modeinfo->red, 0, sizeof (modeinfo->red));
340 memset (&modeinfo->green, 0, sizeof (modeinfo->green));
341 memset (&modeinfo->blue, 0, sizeof (modeinfo->blue));
342 memset (&modeinfo->transp, 0, sizeof (modeinfo->transp));
345 g_warning ("Geometry not specified");
349 modeinfo->xres = geometry[0];
350 modeinfo->yres = geometry[1];
351 modeinfo->xres_virtual = geometry[2];
352 modeinfo->yres_virtual = geometry[3];
353 modeinfo->bits_per_pixel = geometry[4];
357 g_warning ("Timing not specified");
361 modeinfo->pixclock = timings[0];
362 modeinfo->left_margin = timings[1];
363 modeinfo->right_margin = timings[2];
364 modeinfo->upper_margin = timings[3];
365 modeinfo->lower_margin = timings[4];
366 modeinfo->hsync_len = timings[5];
367 modeinfo->vsync_len = timings[6];
371 modeinfo->vmode |= FB_VMODE_INTERLACED;
373 modeinfo->vmode |= FB_VMODE_DOUBLE;
377 modeinfo->sync |= FB_SYNC_HOR_HIGH_ACT;
379 modeinfo->sync |= FB_SYNC_VERT_HIGH_ACT;
381 modeinfo->accel_flags = FB_ACCELF_TEXT;
383 modeinfo->accel_flags = 0;
396 gdk_fb_setup_mode_from_name (struct fb_var_screeninfo *modeinfo,
407 filename = "/etc/fb.modes";
409 fd = open (filename, O_RDONLY);
412 g_warning ("Cannot read %s", filename);
416 scanner = g_scanner_new ((GScannerConfig *) &fb_modes_scanner_config);
417 scanner->input_name = filename;
419 for (i = 0; i < sizeof(fb_modes_keywords)/sizeof(fb_modes_keywords[0]); i++)
420 g_scanner_scope_add_symbol (scanner, 0, fb_modes_keywords[i], GINT_TO_POINTER (i));
422 g_scanner_input_file (scanner, fd);
425 if (g_scanner_peek_next_token (scanner) == G_TOKEN_EOF) {
428 result = fb_modes_parse_mode (scanner, modeinfo, modename);
431 g_warning ("parse error in %s at line %d", filename, scanner->line);
441 g_scanner_destroy (scanner);
450 gdk_fb_set_mode (GdkFBDisplay *display)
453 int depth, height, width;
456 if (ioctl (display->fb_fd, FBIOGET_VSCREENINFO, &display->modeinfo) < 0)
459 display->orig_modeinfo = display->modeinfo;
463 env = getenv ("GDK_DISPLAY_MODE");
466 if (gdk_fb_setup_mode_from_name (&display->modeinfo, env))
469 g_warning ("Couldn't find mode named '%s'", env);
472 env = getenv ("GDK_DISPLAY_DEPTH");
475 depth = strtol (env, &end, 10);
479 display->modeinfo.bits_per_pixel = depth;
483 env = getenv ("GDK_DISPLAY_WIDTH");
486 width = strtol (env, &end, 10);
490 display->modeinfo.xres = width;
491 display->modeinfo.xres_virtual = width;
495 env = getenv ("GDK_DISPLAY_HEIGHT");
498 height = strtol (env, &end, 10);
502 display->modeinfo.yres = height;
503 display->modeinfo.yres_virtual = height;
508 (ioctl (display->fb_fd, FBIOPUT_VSCREENINFO, &display->modeinfo) < 0))
510 g_warning ("Couldn't set specified mode");
514 /* ask for info back to make sure of what we got */
515 if (ioctl (display->fb_fd, FBIOGET_VSCREENINFO, &display->modeinfo) < 0)
517 g_warning ("Error getting var screen info");
521 if (ioctl (display->fb_fd, FBIOGET_FSCREENINFO, &display->sinfo) < 0)
523 g_warning ("Error getting fixed screen info");
529 #ifdef ENABLE_FB_MANAGER
531 gdk_fb_switch_from (void)
533 g_print ("Switch from\n");
534 gdk_shadow_fb_stop_updates ();
535 gdk_fb_mouse_close ();
536 gdk_fb_keyboard_close ();
540 gdk_fb_switch_to (void)
542 g_print ("switch_to\n");
543 gdk_shadow_fb_update (0, 0,
544 gdk_display->fb_width,
545 gdk_display->fb_height);
547 if (!gdk_fb_keyboard_open ())
548 g_warning ("Failed to re-initialize keyboard");
550 if (!gdk_fb_mouse_open ())
551 g_warning ("Failed to re-initialize mouse");
557 gdk_fb_manager_callback (GIOChannel *gioc,
561 struct FBManagerMessage msg;
562 GdkFBDisplay *display;
567 res = recv (display->manager_fd, &msg, sizeof (msg), 0);
571 g_source_remove (gdk_display->manager_tag);
572 /*g_io_channel_unref (kb->io);*/
573 close (gdk_display->manager_fd);
577 if (res != sizeof (msg))
579 g_warning ("Got wrong size message");
583 switch (msg.msg_type)
585 case FB_MANAGER_SWITCH_FROM:
586 g_print ("Got switch from message\n");
587 display->manager_blocked = TRUE;
588 gdk_fb_switch_from ();
589 msg.msg_type = FB_MANAGER_ACK;
590 send (display->manager_fd, &msg, sizeof (msg), 0);
592 case FB_MANAGER_SWITCH_TO:
593 g_print ("Got switch to message\n");
594 display->manager_blocked = FALSE;
598 g_warning ("Got unknown message");
603 #endif /* ENABLE_FB_MANAGER */
606 gdk_fb_manager_connect (GdkFBDisplay *display)
608 #ifdef ENABLE_FB_MANAGER
610 struct sockaddr_un addr;
611 struct msghdr msg = {0};
612 struct cmsghdr *cmsg;
613 struct ucred credentials;
614 struct FBManagerMessage init_msg;
616 char buf[CMSG_SPACE (sizeof (credentials))]; /* ancillary data buffer */
620 display->manager_blocked = FALSE;
621 display->manager_fd = -1;
623 fd = socket (PF_UNIX, SOCK_STREAM, 0);
625 g_print ("socket: %d\n", fd);
630 addr.sun_family = AF_UNIX;
631 strcpy (addr.sun_path, "/tmp/.fb.manager");
633 if (connect(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0)
635 g_print ("connect failed\n");
640 credentials.pid = getpid ();
641 credentials.uid = geteuid ();
642 credentials.gid = getegid ();
644 init_msg.msg_type = FB_MANAGER_NEW_CLIENT;
645 iov.iov_base = &init_msg;
646 iov.iov_len = sizeof (init_msg);
652 msg.msg_control = buf;
653 msg.msg_controllen = sizeof buf;
654 cmsg = CMSG_FIRSTHDR(&msg);
655 cmsg->cmsg_level = SOL_SOCKET;
656 cmsg->cmsg_type = SCM_CREDENTIALS;
657 cmsg->cmsg_len = CMSG_LEN (sizeof (credentials));
658 /* Initialize the payload: */
659 fdptr = (int *)CMSG_DATA (cmsg);
660 memcpy (fdptr, &credentials, sizeof (credentials));
661 /* Sum of the length of all control messages in the buffer: */
662 msg.msg_controllen = cmsg->cmsg_len;
664 res = sendmsg (fd, &msg, 0);
666 display->manager_fd = fd;
667 display->manager_blocked = TRUE;
669 display->manager_tag = g_io_add_watch (g_io_channel_unix_new (fd),
670 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
671 gdk_fb_manager_callback,
674 init_msg.msg_type = FB_MANAGER_REQUEST_SWITCH_TO_PID;
675 init_msg.data = getpid ();
677 /* Request a switch-to */
678 send (fd, &init_msg, sizeof (init_msg), 0);
683 gdk_fb_switch (int sig)
687 ioctl (gdk_display->tty_fd, VT_RELDISP, 1);
688 _gdk_fb_is_active_vt = FALSE;
689 gdk_shadow_fb_stop_updates ();
690 gdk_fb_mouse_close ();
691 gdk_fb_keyboard_close ();
696 ioctl (gdk_display->tty_fd, VT_RELDISP, VT_ACKACQ);
697 _gdk_fb_is_active_vt = TRUE;
699 /* XXX: is it dangerous to put all this stuff in a signal handler? */
700 cmap = gdk_screen_get_default_colormap (_gdk_screen);
701 gdk_colormap_change (cmap, cmap->size);
703 gdk_shadow_fb_update (0, 0,
704 gdk_display->fb_width,
705 gdk_display->fb_height);
707 if (!gdk_fb_keyboard_open ())
708 g_warning ("Failed to re-initialize keyboard");
710 if (!gdk_fb_mouse_open ())
711 g_warning ("Failed to re-initialize mouse");
713 gdk_fb_redraw_all ();
717 static GdkFBDisplay *
718 gdk_fb_display_new ()
720 GdkFBDisplay *display;
728 display = g_new0 (GdkFBDisplay, 1);
730 display->console_fd = open ("/dev/console", O_RDWR);
731 if (display->console_fd < 0)
733 g_warning ("Can't open /dev/console: %s", strerror (errno));
738 ioctl (display->console_fd, VT_GETSTATE, &vs);
739 display->start_vt = vs.v_active;
741 vt = display->start_vt;
742 s = getenv("GDK_VT");
745 if (g_ascii_strcasecmp ("new", s)==0)
747 n = ioctl (display->console_fd, VT_OPENQRY, &vt);
748 if (n < 0 || vt == -1)
749 g_error("Cannot allocate new VT");
753 vt = strtol (s, &send, 10);
756 g_warning ("Cannot parse GDK_VT");
757 vt = display->start_vt;
765 /* Switch to the new VT */
766 if (vt != display->start_vt)
768 ioctl (display->console_fd, VT_ACTIVATE, vt);
769 ioctl (display->console_fd, VT_WAITACTIVE, vt);
773 g_snprintf (buf, sizeof(buf), "/dev/tty%d", vt);
774 display->tty_fd = open (buf, O_RDWR|O_NONBLOCK);
775 if (display->tty_fd < 0)
777 g_warning ("Can't open %s: %s", buf, strerror (errno));
778 close (display->console_fd);
783 /* set up switch signals */
784 if (ioctl (display->tty_fd, VT_GETMODE, &vtm) >= 0)
786 signal (SIGUSR1, gdk_fb_switch);
787 signal (SIGUSR2, gdk_fb_switch);
788 vtm.mode = VT_PROCESS;
790 vtm.relsig = SIGUSR1;
791 vtm.acqsig = SIGUSR2;
792 ioctl (display->tty_fd, VT_SETMODE, &vtm);
794 _gdk_fb_is_active_vt = TRUE;
796 fb_filename = gdk_get_display ();
797 display->fb_fd = open (fb_filename, O_RDWR);
798 if (display->fb_fd < 0)
800 g_warning ("Can't open %s: %s", fb_filename, strerror (errno));
801 g_free (fb_filename);
802 close (display->tty_fd);
803 close (display->console_fd);
807 g_free (fb_filename);
809 if (gdk_fb_set_mode (display) < 0)
811 close (display->fb_fd);
812 close (display->tty_fd);
813 close (display->console_fd);
818 /* Disable normal text on the console */
819 ioctl (display->fb_fd, KDSETMODE, KD_GRAPHICS);
821 ioctl (display->fb_fd, FBIOBLANK, 0);
823 /* We used to use sinfo.smem_len, but that seemed to be broken in many cases */
824 display->fb_mmap = mmap (NULL,
825 display->modeinfo.yres * display->sinfo.line_length,
826 PROT_READ|PROT_WRITE,
830 g_assert (display->fb_mmap != MAP_FAILED);
832 if (display->sinfo.visual == FB_VISUAL_TRUECOLOR)
834 display->red_byte = display->modeinfo.red.offset >> 3;
835 display->green_byte = display->modeinfo.green.offset >> 3;
836 display->blue_byte = display->modeinfo.blue.offset >> 3;
839 #ifdef ENABLE_SHADOW_FB
840 if (_gdk_fb_screen_angle % 2 == 0)
842 display->fb_width = display->modeinfo.xres;
843 display->fb_height = display->modeinfo.yres;
847 display->fb_width = display->modeinfo.yres;
848 display->fb_height = display->modeinfo.xres;
851 display->fb_width * (display->modeinfo.bits_per_pixel / 8);
852 display->fb_mem = g_malloc(display->fb_height * display->fb_stride);
854 display->fb_mem = display->fb_mmap;
855 display->fb_width = display->modeinfo.xres;
856 display->fb_height = display->modeinfo.yres;
857 display->fb_stride = display->sinfo.line_length;
864 gdk_fb_display_destroy (GdkFBDisplay *display)
866 /* Restore old framebuffer mode */
867 ioctl (display->fb_fd, FBIOPUT_VSCREENINFO, &display->orig_modeinfo);
869 /* Enable normal text on the console */
870 ioctl (display->fb_fd, KDSETMODE, KD_TEXT);
872 munmap (display->fb_mmap, display->modeinfo.yres * display->sinfo.line_length);
873 close (display->fb_fd);
875 ioctl (display->console_fd, VT_ACTIVATE, display->start_vt);
876 ioctl (display->console_fd, VT_WAITACTIVE, display->start_vt);
877 if (display->vt != display->start_vt)
878 ioctl (display->console_fd, VT_DISALLOCATE, display->vt);
880 close (display->tty_fd);
881 close (display->console_fd);
886 _gdk_windowing_init (int *argc, char ***argv)
891 /* Create new session and become session leader */
894 gdk_display = gdk_fb_display_new ();
899 gdk_shadow_fb_init ();
901 gdk_fb_manager_connect (gdk_display);
903 if (!gdk_fb_keyboard_init (!gdk_display->manager_blocked))
905 g_warning ("Failed to initialize keyboard");
906 gdk_fb_display_destroy (gdk_display);
911 if (!gdk_fb_mouse_init (!gdk_display->manager_blocked))
913 g_warning ("Failed to initialize mouse");
914 gdk_fb_keyboard_close ();
915 gdk_fb_display_destroy (gdk_display);
920 /* Although atexit is evil, we need it here because otherwise the
921 * keyboard is left in a bad state. you can still run 'reset' but
922 * that gets annoying after running testgtk for the 20th time.
924 g_atexit(_gdk_windowing_exit);
926 gdk_initialized = TRUE;
928 _gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
933 _gdk_windowing_set_default_display (GdkDisplay *display)
938 *--------------------------------------------------------------
941 * Grabs the pointer to a specific window
944 * "window" is the window which will receive the grab
945 * "owner_events" specifies whether events will be reported as is,
946 * or relative to "window"
947 * "event_mask" masks only interesting events
948 * "confine_to" limits the cursor movement to the specified window
949 * "cursor" changes the cursor for the duration of the grab
950 * "time" specifies the time
955 * requires a corresponding call to gdk_pointer_ungrab
957 *--------------------------------------------------------------
961 gdk_pointer_grab (GdkWindow * window,
963 GdkEventMask event_mask,
964 GdkWindow * confine_to,
968 return gdk_fb_pointer_grab (window,
976 static gboolean _gdk_fb_pointer_implicit_grab = FALSE;
979 gdk_fb_pointer_grab (GdkWindow * window,
981 GdkEventMask event_mask,
982 GdkWindow * confine_to,
985 gboolean implicit_grab)
987 g_return_val_if_fail (window != NULL, 0);
988 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
989 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
991 if (_gdk_fb_pointer_grab_window)
993 if (implicit_grab && !_gdk_fb_pointer_implicit_grab)
994 return GDK_GRAB_ALREADY_GRABBED;
996 gdk_pointer_ungrab (time);
999 gdk_fb_window_send_crossing_events (NULL,
1003 if (event_mask & GDK_BUTTON_MOTION_MASK)
1005 GDK_BUTTON1_MOTION_MASK |
1006 GDK_BUTTON2_MOTION_MASK |
1007 GDK_BUTTON3_MOTION_MASK;
1009 _gdk_fb_pointer_implicit_grab = implicit_grab;
1011 _gdk_fb_pointer_grab_window = gdk_window_ref (window);
1012 _gdk_fb_pointer_grab_owner_events = owner_events;
1014 _gdk_fb_pointer_grab_confine = confine_to ? gdk_window_ref (confine_to) : NULL;
1015 _gdk_fb_pointer_grab_events = event_mask;
1016 _gdk_fb_pointer_grab_cursor = cursor ? gdk_cursor_ref (cursor) : NULL;
1021 gdk_fb_cursor_reset ();
1023 return GDK_GRAB_SUCCESS;
1027 *--------------------------------------------------------------
1028 * gdk_display_pointer_ungrab
1030 * Releases any pointer grab
1038 *--------------------------------------------------------------
1042 gdk_display_pointer_ungrab (GdkDisplay *display,
1045 gdk_fb_pointer_ungrab (time, FALSE);
1049 gdk_fb_pointer_ungrab (guint32 time, gboolean implicit_grab)
1051 gboolean have_grab_cursor = _gdk_fb_pointer_grab_cursor && 1;
1052 GdkWindow *mousewin;
1053 GdkWindow *old_grab_window;
1055 if (!_gdk_fb_pointer_grab_window)
1058 if (implicit_grab && !_gdk_fb_pointer_implicit_grab)
1061 if (_gdk_fb_pointer_grab_confine)
1062 gdk_window_unref (_gdk_fb_pointer_grab_confine);
1063 _gdk_fb_pointer_grab_confine = NULL;
1065 if (_gdk_fb_pointer_grab_cursor)
1066 gdk_cursor_unref (_gdk_fb_pointer_grab_cursor);
1067 _gdk_fb_pointer_grab_cursor = NULL;
1069 if (have_grab_cursor)
1070 gdk_fb_cursor_reset ();
1072 old_grab_window = _gdk_fb_pointer_grab_window;
1074 _gdk_fb_pointer_grab_window = NULL;
1076 _gdk_fb_pointer_implicit_grab = FALSE;
1078 mousewin = gdk_window_at_pointer (NULL, NULL);
1079 gdk_fb_window_send_crossing_events (old_grab_window,
1081 GDK_CROSSING_UNGRAB);
1083 if (old_grab_window)
1084 gdk_window_unref (old_grab_window);
1088 *--------------------------------------------------------------
1089 * gdk_display_pointer_is_grabbed
1091 * Tell wether there is an active x pointer grab in effect
1099 *--------------------------------------------------------------
1103 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1105 return _gdk_fb_pointer_grab_window != NULL;
1109 *--------------------------------------------------------------
1112 * Grabs the keyboard to a specific window
1115 * "window" is the window which will receive the grab
1116 * "owner_events" specifies whether events will be reported as is,
1117 * or relative to "window"
1118 * "time" specifies the time
1123 * requires a corresponding call to gdk_keyboard_ungrab
1125 *--------------------------------------------------------------
1129 gdk_keyboard_grab (GdkWindow *window,
1133 g_return_val_if_fail (window != NULL, 0);
1134 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1136 if (_gdk_fb_pointer_grab_window)
1137 gdk_keyboard_ungrab (time);
1139 _gdk_fb_keyboard_grab_window = gdk_window_ref (window);
1140 _gdk_fb_keyboard_grab_owner_events = owner_events;
1142 return GDK_GRAB_SUCCESS;
1146 *--------------------------------------------------------------
1147 * gdk_display_keyboard_ungrab
1149 * Releases any keyboard grab
1157 *--------------------------------------------------------------
1161 gdk_display_keyboard_ungrab (GdkDisplay *display,
1164 if (_gdk_fb_keyboard_grab_window)
1165 gdk_window_unref (_gdk_fb_keyboard_grab_window);
1166 _gdk_fb_keyboard_grab_window = NULL;
1170 gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1171 GdkWindow **grab_window,
1172 gboolean *owner_events)
1174 if (_gdk_fb_pointer_grab_window)
1177 *grab_window = (GdkWindow *)_gdk_fb_pointer_grab_window;
1179 *owner_events = _gdk_fb_pointer_grab_owner_events;
1188 gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1189 GdkWindow **grab_window,
1190 gboolean *owner_events)
1192 if (_gdk_fb_keyboard_grab_window)
1195 *grab_window = (GdkWindow *)_gdk_fb_keyboard_grab_window;
1197 *owner_events = _gdk_fb_keyboard_grab_owner_events;
1207 *--------------------------------------------------------------
1208 * gdk_screen_get_width
1210 * Return the width of the screen.
1218 *--------------------------------------------------------------
1222 gdk_screen_get_width (GdkScreen *screen)
1224 return gdk_display->fb_width;
1228 *--------------------------------------------------------------
1229 * gdk_screen_get_height
1231 * Return the height of the screen.
1239 *--------------------------------------------------------------
1243 gdk_screen_get_height (GdkScreen *screen)
1245 return gdk_display->fb_height;
1249 *--------------------------------------------------------------
1250 * gdk_screen_get_width_mm
1252 * Return the width of the screen in millimeters.
1260 *--------------------------------------------------------------
1264 gdk_screen_get_width_mm (GdkScreen *screen)
1266 return 0.5 + gdk_screen_width () * (25.4 / 72.);
1270 *--------------------------------------------------------------
1271 * gdk_screen_get_height_mm
1273 * Return the height of the screen in millimeters.
1281 *--------------------------------------------------------------
1285 gdk_screen_get_height_mm (GdkScreen *screen)
1287 return 0.5 + gdk_screen_height () * (25.4 / 72.);
1291 _gdk_windowing_display_set_sm_client_id (GdkDisplay* display,
1292 const gchar* sm_client_id)
1296 extern void keyboard_shutdown(void);
1299 _gdk_windowing_exit (void)
1301 struct sigaction action;
1303 /* don't get interrupted while exiting
1304 * (cf. gdkrender-fb.c:gdk_shadow_fb_init) */
1305 action.sa_handler = SIG_IGN;
1306 sigemptyset (&action.sa_mask);
1307 action.sa_flags = 0;
1309 gdk_fb_mouse_close ();
1310 /*leak g_free (gdk_fb_mouse);*/
1312 gdk_fb_keyboard_close ();
1313 /*leak g_free (gdk_fb_keyboard);*/
1315 gdk_fb_display_destroy (gdk_display);
1321 gdk_get_display(void)
1325 s = getenv ("GDK_DISPLAY");
1329 return g_strdup (s);
1333 gdk_display_beep (GdkDisplay *display)
1335 static int pitch = 600, duration = 100;
1338 /* Thank you XFree86 */
1339 arg = ((1193190 / pitch) & 0xffff) |
1340 (((unsigned long)duration) << 16);
1342 ioctl (gdk_display->tty_fd, KDMKTONE, arg);
1346 static const guint type_masks[] = {
1347 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0, */
1348 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1, */
1349 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2, */
1350 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3, */
1351 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4, */
1352 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5, */
1353 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6, */
1354 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7, */
1355 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8, */
1356 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9, */
1357 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10, */
1358 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11, */
1359 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12, */
1360 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13, */
1361 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14, */
1362 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15, */
1363 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16, */
1364 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17, */
1365 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18, */
1366 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19, */
1367 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20, */
1368 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21, */
1369 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22, */
1370 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23, */
1371 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24, */
1372 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25, */
1373 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26, */
1374 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27, */
1375 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28, */
1376 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29, */
1377 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30, */
1378 GDK_SCROLL_MASK /* GDK_SCROLL = 31 */
1382 gdk_fb_other_event_window (GdkWindow *window,
1389 while (w != _gdk_parent_root)
1391 /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1392 if ((w != window) &&
1393 (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1394 (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1397 evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1399 if (evmask & type_masks[type])
1402 w = gdk_window_get_parent (w);
1409 gdk_fb_pointer_event_window (GdkWindow *window,
1413 GdkModifierType mask;
1416 gdk_fb_mouse_get_info (NULL, NULL, &mask);
1418 if (_gdk_fb_pointer_grab_window &&
1419 !_gdk_fb_pointer_grab_owner_events)
1421 evmask = _gdk_fb_pointer_grab_events;
1423 if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1425 if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1426 ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1427 ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1428 evmask |= GDK_POINTER_MOTION_MASK;
1431 if (evmask & type_masks[type])
1432 return _gdk_fb_pointer_grab_window;
1438 while (w != _gdk_parent_root)
1440 /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1441 if ((w != window) &&
1442 (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1443 (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1446 evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1448 if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1450 if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1451 ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1452 ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1453 evmask |= GDK_POINTER_MOTION_MASK;
1456 if (evmask & type_masks[type])
1459 w = gdk_window_get_parent (w);
1462 if (_gdk_fb_pointer_grab_window &&
1463 _gdk_fb_pointer_grab_owner_events)
1465 evmask = _gdk_fb_pointer_grab_events;
1467 if (evmask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK))
1469 if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) ||
1470 ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) ||
1471 ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
1472 evmask |= GDK_POINTER_MOTION_MASK;
1475 if (evmask & type_masks[type])
1476 return _gdk_fb_pointer_grab_window;
1483 gdk_fb_keyboard_event_window (GdkWindow *window,
1489 if (_gdk_fb_keyboard_grab_window &&
1490 !_gdk_fb_keyboard_grab_owner_events)
1492 return _gdk_fb_keyboard_grab_window;
1496 while (w != _gdk_parent_root)
1498 /* Huge hack, so that we don't propagate events to GtkWindow->frame */
1499 if ((w != window) &&
1500 (GDK_WINDOW_P (w)->window_type != GDK_WINDOW_CHILD) &&
1501 (g_object_get_data (G_OBJECT (w), "gdk-window-child-handler")))
1504 evmask = GDK_WINDOW_OBJECT(window)->event_mask;
1506 if (evmask & type_masks[type])
1509 w = gdk_window_get_parent (w);
1512 if (_gdk_fb_keyboard_grab_window &&
1513 _gdk_fb_keyboard_grab_owner_events)
1515 return _gdk_fb_keyboard_grab_window;
1522 gdk_event_make (GdkWindow *window,
1524 gboolean append_to_queue)
1526 GdkEvent *event = gdk_event_new (type);
1529 the_time = gdk_fb_get_time ();
1531 event->any.window = gdk_window_ref (window);
1532 event->any.send_event = FALSE;
1535 case GDK_MOTION_NOTIFY:
1536 event->motion.time = the_time;
1537 event->motion.axes = NULL;
1539 case GDK_BUTTON_PRESS:
1540 case GDK_2BUTTON_PRESS:
1541 case GDK_3BUTTON_PRESS:
1542 case GDK_BUTTON_RELEASE:
1543 event->button.time = the_time;
1544 event->button.axes = NULL;
1547 case GDK_KEY_RELEASE:
1548 event->key.time = the_time;
1550 case GDK_ENTER_NOTIFY:
1551 case GDK_LEAVE_NOTIFY:
1552 event->crossing.time = the_time;
1555 case GDK_PROPERTY_NOTIFY:
1556 event->property.time = the_time;
1559 case GDK_SELECTION_CLEAR:
1560 case GDK_SELECTION_REQUEST:
1561 case GDK_SELECTION_NOTIFY:
1562 event->selection.time = the_time;
1564 case GDK_PROXIMITY_IN:
1565 case GDK_PROXIMITY_OUT:
1566 event->proximity.time = the_time;
1568 case GDK_DRAG_ENTER:
1569 case GDK_DRAG_LEAVE:
1570 case GDK_DRAG_MOTION:
1571 case GDK_DRAG_STATUS:
1572 case GDK_DROP_START:
1573 case GDK_DROP_FINISHED:
1574 event->dnd.time = the_time;
1577 case GDK_FOCUS_CHANGE:
1581 case GDK_CLIENT_EVENT:
1582 case GDK_VISIBILITY_NOTIFY:
1592 if (append_to_queue)
1593 _gdk_event_queue_append (gdk_display_get_default (), event);
1599 gdk_fb_set_rotation (GdkFBAngle angle)
1601 if (angle == _gdk_fb_screen_angle)
1604 #ifdef ENABLE_SHADOW_FB
1607 gdk_shadow_fb_stop_updates ();
1609 gdk_fb_cursor_hide ();
1611 _gdk_fb_screen_angle = angle;
1615 gdk_display->fb_width = gdk_display->modeinfo.xres;
1616 gdk_display->fb_height = gdk_display->modeinfo.yres;
1620 gdk_display->fb_width = gdk_display->modeinfo.yres;
1621 gdk_display->fb_height = gdk_display->modeinfo.xres;
1623 gdk_display->fb_stride =
1624 gdk_display->fb_width * (gdk_display->modeinfo.bits_per_pixel / 8);
1626 gdk_fb_recompute_all();
1627 gdk_fb_redraw_all ();
1629 gdk_fb_cursor_unhide ();
1632 _gdk_fb_screen_angle = angle;
1634 g_warning ("Screen rotation without shadow fb not supported.");
1639 gdk_error_trap_push (void)
1644 gdk_error_trap_pop (void)
1650 gdk_notify_startup_complete (void)