nkeynes@94: /** nkeynes@586: * $Id$ nkeynes@94: * nkeynes@94: * The PC side of the video support (responsible for actually displaying / nkeynes@94: * rendering frames) nkeynes@94: * nkeynes@94: * Copyright (c) 2005 Nathan Keynes. nkeynes@94: * nkeynes@94: * This program is free software; you can redistribute it and/or modify nkeynes@94: * it under the terms of the GNU General Public License as published by nkeynes@94: * the Free Software Foundation; either version 2 of the License, or nkeynes@94: * (at your option) any later version. nkeynes@94: * nkeynes@94: * This program is distributed in the hope that it will be useful, nkeynes@94: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@94: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@94: * GNU General Public License for more details. nkeynes@94: */ nkeynes@94: nkeynes@485: #include nkeynes@94: #include nkeynes@677: #include nkeynes@658: #include "lxdream.h" nkeynes@144: #include "display.h" nkeynes@608: #include "dckeysyms.h" nkeynes@635: #include "drivers/video_gl.h" nkeynes@669: #include "drivers/joy_linux.h" nkeynes@586: #include "pvr2/pvr2.h" nkeynes@537: #include "gtkui/gtkui.h" nkeynes@94: nkeynes@658: #ifdef HAVE_GTK_X11 nkeynes@658: nkeynes@658: #include nkeynes@658: #include "drivers/video_glx.h" nkeynes@658: nkeynes@658: /************* X11-specificness **********/ nkeynes@658: nkeynes@658: guint gdk_keycode_to_modifier( GdkDisplay *display, guint keycode ) nkeynes@658: { nkeynes@736: int i; nkeynes@736: int result = 0; nkeynes@736: Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); nkeynes@736: XModifierKeymap *keymap = XGetModifierMapping( xdisplay ); nkeynes@736: for( i=0; i<8*keymap->max_keypermod; i++ ) { nkeynes@736: if( keymap->modifiermap[i] == keycode ) { nkeynes@736: result = 1 << (i/keymap->max_keypermod); nkeynes@736: break; nkeynes@736: } nkeynes@658: } nkeynes@736: XFreeModifiermap(keymap); nkeynes@736: return result; nkeynes@658: } nkeynes@658: nkeynes@658: #if !(GTK_CHECK_VERSION(2,8,0)) nkeynes@658: /* gdk_display_warp_pointer was added in GTK 2.8. If we're using an earlier nkeynes@658: * version, include the code here. (Can't just set the dependency on 2.8 as nkeynes@658: * it still hasn't been included in fink yet...) Original copyright statement nkeynes@658: * below. nkeynes@658: */ nkeynes@658: nkeynes@658: /* GDK - The GIMP Drawing Kit nkeynes@658: * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald nkeynes@658: * nkeynes@658: * This library is free software; you can redistribute it and/or nkeynes@658: * modify it under the terms of the GNU Lesser General Public nkeynes@658: * License as published by the Free Software Foundation; either nkeynes@658: * version 2 of the License, or (at your option) any later version. nkeynes@658: * nkeynes@658: * This library is distributed in the hope that it will be useful, nkeynes@658: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@658: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nkeynes@658: * Lesser General Public License for more details. nkeynes@658: * nkeynes@658: * You should have received a copy of the GNU Lesser General Public nkeynes@658: * License along with this library; if not, write to the nkeynes@658: * Free Software Foundation, Inc., 59 Temple Place - Suite 330, nkeynes@658: * Boston, MA 02111-1307, USA. nkeynes@658: */ nkeynes@658: nkeynes@658: /* nkeynes@658: * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS nkeynes@658: * file for a list of people on the GTK+ Team. See the ChangeLog nkeynes@658: * files for a list of changes. These files are distributed with nkeynes@658: * GTK+ at ftp://ftp.gtk.org/pub/gtk/. nkeynes@658: */ nkeynes@658: void gdk_display_warp_pointer (GdkDisplay *display, nkeynes@736: GdkScreen *screen, nkeynes@736: gint x, nkeynes@736: gint y) nkeynes@658: { nkeynes@736: Display *xdisplay; nkeynes@736: Window dest; nkeynes@658: nkeynes@736: xdisplay = GDK_DISPLAY_XDISPLAY (display); nkeynes@736: dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)); nkeynes@658: nkeynes@736: XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y); nkeynes@658: } nkeynes@658: nkeynes@658: #endif nkeynes@658: nkeynes@658: #endif nkeynes@659: nkeynes@663: #ifdef HAVE_GTK_OSX nkeynes@663: #include "drivers/video_nsgl.h" nkeynes@663: nkeynes@663: // Include this prototype as some systems don't have gdkquartz.h installed nkeynes@663: NSView *gdk_quartz_window_get_nsview( GdkWindow *window); nkeynes@663: nkeynes@663: guint gdk_keycode_to_modifier( GdkDisplay *display, guint keycode ) nkeynes@663: { nkeynes@736: return 0; nkeynes@663: } nkeynes@663: nkeynes@663: #endif nkeynes@663: nkeynes@663: nkeynes@663: nkeynes@661: GtkWidget *gtk_video_drawable = NULL; nkeynes@94: nkeynes@352: gboolean video_gtk_init(); nkeynes@352: void video_gtk_shutdown(); nkeynes@669: void video_gtk_display_blank( uint32_t colour ); nkeynes@770: static uint16_t video_gtk_resolve_keysym( const gchar *keysym ); nkeynes@770: static uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode); nkeynes@771: static gchar *video_gtk_keycode_to_keysym(uint16_t keycode); nkeynes@94: nkeynes@700: struct display_driver display_gtk_driver = { nkeynes@700: "gtk", nkeynes@700: N_("GTK-based OpenGL driver"), nkeynes@700: video_gtk_init, nkeynes@700: video_gtk_shutdown, nkeynes@700: video_gtk_resolve_keysym, nkeynes@700: video_gtk_keycode_to_dckeysym, nkeynes@770: video_gtk_keycode_to_keysym, nkeynes@805: NULL, NULL, NULL, NULL, NULL, NULL, nkeynes@1076: video_gtk_display_blank, NULL, NULL }; nkeynes@144: nkeynes@435: gboolean video_gtk_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data ) nkeynes@435: { nkeynes@1076: pvr2_draw_frame(); nkeynes@443: return TRUE; nkeynes@435: } nkeynes@435: nkeynes@436: gboolean video_gtk_resize_callback(GtkWidget *widget, GdkEventConfigure *event, gpointer data ) nkeynes@436: { nkeynes@1236: gl_set_video_size(event->width, event->height); nkeynes@1076: pvr2_draw_frame(); nkeynes@443: return TRUE; nkeynes@436: } nkeynes@436: nkeynes@770: static uint16_t video_gtk_resolve_keysym( const gchar *keysym ) nkeynes@770: { nkeynes@770: int val = gdk_keyval_from_name( keysym ); nkeynes@770: if( val == GDK_VoidSymbol ) nkeynes@770: return 0; nkeynes@770: return (uint16_t)val; nkeynes@770: } nkeynes@770: nkeynes@771: static gchar *video_gtk_keycode_to_keysym( uint16_t keycode ) nkeynes@770: { nkeynes@770: return g_strdup(gdk_keyval_name(keycode)); nkeynes@770: } nkeynes@770: nkeynes@770: static uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode) nkeynes@608: { nkeynes@608: if( keycode >= 'a' && keycode <= 'z' ) { nkeynes@736: return (keycode - 'a') + DCKB_a; nkeynes@608: } else if( keycode >= '1' && keycode <= '9' ) { nkeynes@736: return (keycode - '1') + DCKB_1; nkeynes@608: } nkeynes@608: switch(keycode) { nkeynes@609: case GDK_0: return DCKB_0; nkeynes@681: case GDK_Return: return DCKB_Return; nkeynes@681: case GDK_Escape: return DCKB_Escape; nkeynes@681: case GDK_BackSpace: return DCKB_BackSpace; nkeynes@681: case GDK_Tab: return DCKB_Tab; nkeynes@681: case GDK_space: return DCKB_space; nkeynes@681: case GDK_minus: return DCKB_minus; nkeynes@681: case GDK_equal: return DCKB_equal; nkeynes@681: case GDK_bracketleft: return DCKB_bracketleft; nkeynes@681: case GDK_bracketright: return DCKB_bracketright; nkeynes@681: case GDK_semicolon: return DCKB_semicolon; nkeynes@681: case GDK_apostrophe:return DCKB_apostrophe; nkeynes@681: case GDK_grave : return DCKB_grave; nkeynes@681: case GDK_comma: return DCKB_comma; nkeynes@681: case GDK_period: return DCKB_period; nkeynes@681: case GDK_slash: return DCKB_slash; nkeynes@681: case GDK_Caps_Lock: return DCKB_Caps_Lock; nkeynes@609: case GDK_F1: return DCKB_F1; nkeynes@609: case GDK_F2: return DCKB_F2; nkeynes@609: case GDK_F3: return DCKB_F3; nkeynes@609: case GDK_F4: return DCKB_F4; nkeynes@609: case GDK_F5: return DCKB_F5; nkeynes@609: case GDK_F6: return DCKB_F6; nkeynes@609: case GDK_F7: return DCKB_F7; nkeynes@609: case GDK_F8: return DCKB_F8; nkeynes@609: case GDK_F9: return DCKB_F9; nkeynes@609: case GDK_F10: return DCKB_F10; nkeynes@609: case GDK_F11: return DCKB_F11; nkeynes@609: case GDK_F12: return DCKB_F12; nkeynes@681: case GDK_Scroll_Lock: return DCKB_Scroll_Lock; nkeynes@681: case GDK_Pause: return DCKB_Pause; nkeynes@681: case GDK_Insert: return DCKB_Insert; nkeynes@681: case GDK_Home: return DCKB_Home; nkeynes@681: case GDK_Page_Up: return DCKB_Page_Up; nkeynes@681: case GDK_Delete: return DCKB_Delete; nkeynes@682: case GDK_End: return DCKB_End; nkeynes@681: case GDK_Page_Down: return DCKB_Page_Down; nkeynes@681: case GDK_Right: return DCKB_Right; nkeynes@681: case GDK_Left: return DCKB_Left; nkeynes@681: case GDK_Down: return DCKB_Down; nkeynes@681: case GDK_Up: return DCKB_Up; nkeynes@681: case GDK_Num_Lock: return DCKB_Num_Lock; nkeynes@681: case GDK_KP_Divide: return DCKB_KP_Divide; nkeynes@681: case GDK_KP_Multiply: return DCKB_KP_Multiply; nkeynes@681: case GDK_KP_Subtract: return DCKB_KP_Subtract; nkeynes@681: case GDK_KP_Add: return DCKB_KP_Add; nkeynes@681: case GDK_KP_Enter: return DCKB_KP_Enter; nkeynes@681: case GDK_KP_End: return DCKB_KP_End; nkeynes@681: case GDK_KP_Down: return DCKB_KP_Down; nkeynes@681: case GDK_KP_Page_Down: return DCKB_KP_Page_Down; nkeynes@681: case GDK_KP_Left: return DCKB_KP_Left; nkeynes@681: case GDK_KP_Begin: return DCKB_KP_Begin; nkeynes@681: case GDK_KP_Right: return DCKB_KP_Right; nkeynes@681: case GDK_KP_Home: return DCKB_KP_Home; nkeynes@681: case GDK_KP_Up: return DCKB_KP_Up; nkeynes@681: case GDK_KP_Page_Up:return DCKB_KP_Page_Up; nkeynes@681: case GDK_KP_Insert: return DCKB_KP_Insert; nkeynes@681: case GDK_KP_Delete: return DCKB_KP_Delete; nkeynes@681: case GDK_backslash: return DCKB_backslash; nkeynes@681: case GDK_Control_L: return DCKB_Control_L; nkeynes@681: case GDK_Shift_L: return DCKB_Shift_L; nkeynes@681: case GDK_Alt_L: return DCKB_Alt_L; nkeynes@681: case GDK_Meta_L: return DCKB_Meta_L; nkeynes@681: case GDK_Control_R: return DCKB_Control_R; nkeynes@681: case GDK_Shift_R: return DCKB_Shift_R; nkeynes@681: case GDK_Alt_R: return DCKB_Alt_R; nkeynes@681: case GDK_Meta_R: return DCKB_Meta_R; nkeynes@608: } nkeynes@608: return DCKB_NONE; nkeynes@608: } nkeynes@608: nkeynes@659: GtkWidget *video_gtk_create_drawable() nkeynes@659: { nkeynes@659: GtkWidget *drawable = gtk_drawing_area_new(); nkeynes@659: GTK_WIDGET_SET_FLAGS(drawable, GTK_CAN_FOCUS|GTK_CAN_DEFAULT); nkeynes@659: nkeynes@659: g_signal_connect( drawable, "expose_event", nkeynes@736: G_CALLBACK(video_gtk_expose_callback), NULL ); nkeynes@659: g_signal_connect( drawable, "configure_event", nkeynes@736: G_CALLBACK(video_gtk_resize_callback), NULL ); nkeynes@659: nkeynes@659: #ifdef HAVE_GLX nkeynes@659: Display *display = gdk_x11_display_get_xdisplay( gtk_widget_get_display(drawable)); nkeynes@659: Screen *screen = gdk_x11_screen_get_xscreen( gtk_widget_get_screen(drawable)); nkeynes@659: int screen_no = XScreenNumberOfScreen(screen); nkeynes@659: if( !video_glx_init(display, screen_no) ) { nkeynes@659: ERROR( "Unable to initialize GLX, aborting" ); nkeynes@659: exit(3); nkeynes@659: } nkeynes@659: nkeynes@659: XVisualInfo *visual = video_glx_get_visual(); nkeynes@659: if( visual != NULL ) { nkeynes@659: GdkVisual *gdkvis = gdk_x11_screen_lookup_visual( gtk_widget_get_screen(drawable), visual->visualid ); nkeynes@659: GdkColormap *colormap = gdk_colormap_new( gdkvis, FALSE ); nkeynes@659: gtk_widget_set_colormap( drawable, colormap ); nkeynes@659: } nkeynes@659: #endif nkeynes@659: gtk_video_drawable = drawable; nkeynes@659: return drawable; nkeynes@659: } nkeynes@659: nkeynes@352: gboolean video_gtk_init() nkeynes@94: { nkeynes@736: nkeynes@659: if( gtk_video_drawable == NULL ) { nkeynes@736: return FALSE; nkeynes@530: } nkeynes@435: nkeynes@1236: gl_set_video_size(gtk_video_drawable->allocation.width, gtk_video_drawable->allocation.height); nkeynes@658: #ifdef HAVE_OSMESA nkeynes@635: video_gdk_init_driver( &display_gtk_driver ); nkeynes@635: #else nkeynes@658: #ifdef HAVE_GLX nkeynes@659: Display *display = gdk_x11_display_get_xdisplay( gtk_widget_get_display(GTK_WIDGET(gtk_video_drawable))); nkeynes@659: Window window = GDK_WINDOW_XWINDOW( GTK_WIDGET(gtk_video_drawable)->window ); nkeynes@552: if( ! video_glx_init_context( display, window ) || nkeynes@736: ! video_glx_init_driver( &display_gtk_driver ) ) { nkeynes@552: return FALSE; nkeynes@552: } nkeynes@663: #else nkeynes@663: #ifdef HAVE_NSGL nkeynes@663: NSView *view = gdk_quartz_window_get_nsview(gtk_video_drawable->window); nkeynes@663: if( ! video_nsgl_init_driver( view, &display_gtk_driver ) ) { nkeynes@552: return FALSE; nkeynes@552: } nkeynes@635: #endif nkeynes@653: #endif nkeynes@658: #endif nkeynes@653: nkeynes@665: pvr2_setup_gl_context(); nkeynes@635: nkeynes@614: #ifdef HAVE_LINUX_JOYSTICK nkeynes@614: linux_joystick_init(); nkeynes@614: #endif nkeynes@552: return TRUE; nkeynes@552: } nkeynes@552: nkeynes@669: void video_gtk_display_blank( uint32_t colour ) nkeynes@552: { nkeynes@659: GdkGC *gc = gdk_gc_new(gtk_video_drawable->window); nkeynes@552: GdkColor color = {0, ((colour>>16)&0xFF)*257, ((colour>>8)&0xFF)*257, ((colour)&0xFF)*257 }; nkeynes@552: GdkColormap *cmap = gdk_colormap_get_system(); nkeynes@552: gdk_colormap_alloc_color( cmap, &color, TRUE, TRUE ); nkeynes@552: gdk_gc_set_foreground( gc, &color ); nkeynes@552: gdk_gc_set_background( gc, &color ); nkeynes@659: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, 0, 0, video_width, video_height ); nkeynes@552: gdk_gc_destroy(gc); nkeynes@552: gdk_colormap_free_colors( cmap, &color, 1 ); nkeynes@94: } nkeynes@94: nkeynes@352: void video_gtk_shutdown() nkeynes@352: { nkeynes@659: if( gtk_video_drawable != NULL ) { nkeynes@658: #ifdef HAVE_OSMESA nkeynes@635: video_gdk_shutdown(); nkeynes@635: #else nkeynes@659: #ifdef HAVE_GLX nkeynes@736: video_glx_shutdown(); nkeynes@663: #else nkeynes@663: #ifdef HAVE_NSGL nkeynes@736: video_nsgl_shutdown(); nkeynes@663: #endif nkeynes@653: #endif nkeynes@635: #endif nkeynes@530: } nkeynes@620: #ifdef HAVE_LINUX_JOYSTICK nkeynes@620: linux_joystick_shutdown(); nkeynes@620: #endif nkeynes@94: } nkeynes@94: