]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkmain-fb.c
applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[~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
38 #include "gdk.h"
39
40 #include "gdkprivate-fb.h"
41 #include "gdkinternals.h"
42
43 /* Private variable declarations
44  */
45 static int gdk_initialized = 0;                     /* 1 if the library is initialized,
46                                                      * 0 otherwise.
47                                                      */
48
49 #ifdef G_ENABLE_DEBUG
50 static const GDebugKey gdk_debug_keys[] = {
51   {"misc",          GDK_DEBUG_MISC},
52   {"events",        GDK_DEBUG_EVENTS},
53 };
54
55 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
56
57 #endif /* G_ENABLE_DEBUG */
58
59 GdkArgDesc _gdk_windowing_args[] = {
60   { NULL }
61 };
62
63 static GdkFBDisplay *
64 gdk_fb_display_new(const char *filename)
65 {
66   int fd, n;
67   GdkFBDisplay *retval;
68
69   fd = open(filename, O_RDWR);
70   if(fd < 0)
71     return NULL;
72
73   retval = g_new0(GdkFBDisplay, 1);
74   retval->fd = fd;
75   n = ioctl(fd, FBIOGET_FSCREENINFO, &retval->sinfo);
76   n |= ioctl(fd, FBIOGET_VSCREENINFO, &retval->modeinfo);
77   g_assert(!n);
78
79   /* We used to use sinfo.smem_len, but that seemed to be broken in many cases */
80   retval->fbmem = mmap(NULL, retval->modeinfo.yres * retval->sinfo.line_length,
81                        PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
82   g_assert(retval->fbmem != MAP_FAILED);
83
84   if(retval->sinfo.visual == FB_VISUAL_PSEUDOCOLOR)
85     {
86       guint16 red[256], green[256], blue[256];
87       struct fb_cmap cmap;
88       for(n = 0; n < 16; n++)
89         red[n] = green[n] = blue[n] = n << 12;
90       for(n = 16; n < 256; n++)
91         red[n] = green[n] = blue[n] = n << 8;
92       cmap.red = red; cmap.green = green; cmap.blue = blue; cmap.len = 256; cmap.start = 0;
93       ioctl(fd, FBIOPUTCMAP, &cmap);
94     }
95
96   if(retval->sinfo.visual == FB_VISUAL_TRUECOLOR)
97     {
98       retval->red_byte = retval->modeinfo.red.offset >> 3;
99       retval->green_byte = retval->modeinfo.green.offset >> 3;
100       retval->blue_byte = retval->modeinfo.blue.offset >> 3;
101     }
102
103   return retval;
104 }
105
106 static void
107 gdk_fb_display_destroy(GdkFBDisplay *fbd)
108 {
109   munmap(fbd->fbmem, fbd->modeinfo.yres * fbd->sinfo.line_length);
110   close(fbd->fd);
111   g_free(fbd);
112 }
113
114 extern void keyboard_init(void);
115
116 gboolean
117 _gdk_windowing_init_check (int argc, char **argv)
118 {
119   if(gdk_initialized)
120     return TRUE;
121
122   keyboard_init();
123   gdk_display = gdk_fb_display_new("/dev/fb");
124
125   if(!gdk_display)
126     return FALSE;
127
128   gdk_fb_font_init();
129
130   gdk_initialized = TRUE;
131
132   return TRUE;
133 }
134
135 /*
136  *--------------------------------------------------------------
137  * gdk_pointer_grab
138  *
139  *   Grabs the pointer to a specific window
140  *
141  * Arguments:
142  *   "window" is the window which will receive the grab
143  *   "owner_events" specifies whether events will be reported as is,
144  *     or relative to "window"
145  *   "event_mask" masks only interesting events
146  *   "confine_to" limits the cursor movement to the specified window
147  *   "cursor" changes the cursor for the duration of the grab
148  *   "time" specifies the time
149  *
150  * Results:
151  *
152  * Side effects:
153  *   requires a corresponding call to gdk_pointer_ungrab
154  *
155  *--------------------------------------------------------------
156  */
157
158 GdkGrabStatus
159 gdk_pointer_grab (GdkWindow *     window,
160                   gint            owner_events,
161                   GdkEventMask    event_mask,
162                   GdkWindow *     confine_to,
163                   GdkCursor *     cursor,
164                   guint32         time)
165 {
166   g_return_val_if_fail (window != NULL, 0);
167   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
168   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
169
170   if(_gdk_fb_pointer_grab_window)
171     gdk_pointer_ungrab(time);
172
173   if(!owner_events)
174     _gdk_fb_pointer_grab_window = gdk_window_ref(window);
175
176   _gdk_fb_pointer_grab_confine = confine_to?gdk_window_ref(confine_to):NULL;
177   _gdk_fb_pointer_grab_events = event_mask;
178   _gdk_fb_pointer_grab_cursor = cursor?gdk_cursor_ref(cursor):NULL;
179
180   if(cursor)
181     gdk_fb_cursor_reset();
182   
183   return GDK_GRAB_SUCCESS;
184 }
185
186 /*
187  *--------------------------------------------------------------
188  * gdk_pointer_ungrab
189  *
190  *   Releases any pointer grab
191  *
192  * Arguments:
193  *
194  * Results:
195  *
196  * Side effects:
197  *
198  *--------------------------------------------------------------
199  */
200
201 void
202 gdk_pointer_ungrab (guint32 time)
203 {
204   gboolean have_grab_cursor = _gdk_fb_pointer_grab_cursor && 1;
205
206   if(_gdk_fb_pointer_grab_window)
207     gdk_window_unref(_gdk_fb_pointer_grab_window);
208   _gdk_fb_pointer_grab_window = NULL;
209
210   if(_gdk_fb_pointer_grab_confine)
211     gdk_window_unref(_gdk_fb_pointer_grab_confine);
212   _gdk_fb_pointer_grab_confine = NULL;
213
214   if(_gdk_fb_pointer_grab_cursor)
215     gdk_cursor_unref(_gdk_fb_pointer_grab_cursor);
216   _gdk_fb_pointer_grab_cursor = NULL;
217
218   if(have_grab_cursor)
219     gdk_fb_cursor_reset();
220 }
221
222 /*
223  *--------------------------------------------------------------
224  * gdk_pointer_is_grabbed
225  *
226  *   Tell wether there is an active x pointer grab in effect
227  *
228  * Arguments:
229  *
230  * Results:
231  *
232  * Side effects:
233  *
234  *--------------------------------------------------------------
235  */
236
237 gint
238 gdk_pointer_is_grabbed (void)
239 {
240   return _gdk_fb_pointer_grab_window != NULL;
241 }
242
243 /*
244  *--------------------------------------------------------------
245  * gdk_keyboard_grab
246  *
247  *   Grabs the keyboard to a specific window
248  *
249  * Arguments:
250  *   "window" is the window which will receive the grab
251  *   "owner_events" specifies whether events will be reported as is,
252  *     or relative to "window"
253  *   "time" specifies the time
254  *
255  * Results:
256  *
257  * Side effects:
258  *   requires a corresponding call to gdk_keyboard_ungrab
259  *
260  *--------------------------------------------------------------
261  */
262
263 GdkGrabStatus
264 gdk_keyboard_grab (GdkWindow *     window,
265                    gint            owner_events,
266                    guint32         time)
267 {
268   g_return_val_if_fail (window != NULL, 0);
269   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
270
271   if(_gdk_fb_pointer_grab_window)
272     gdk_keyboard_ungrab(time);
273
274   if(!owner_events)
275     _gdk_fb_keyboard_grab_window = gdk_window_ref(window);
276   
277   return GDK_GRAB_SUCCESS;
278 }
279
280 /*
281  *--------------------------------------------------------------
282  * gdk_keyboard_ungrab
283  *
284  *   Releases any keyboard grab
285  *
286  * Arguments:
287  *
288  * Results:
289  *
290  * Side effects:
291  *
292  *--------------------------------------------------------------
293  */
294
295 void
296 gdk_keyboard_ungrab (guint32 time)
297 {
298   if(_gdk_fb_keyboard_grab_window)
299     gdk_window_unref(_gdk_fb_keyboard_grab_window);
300   _gdk_fb_keyboard_grab_window = NULL;
301 }
302
303 /*
304  *--------------------------------------------------------------
305  * gdk_screen_width
306  *
307  *   Return the width of the screen.
308  *
309  * Arguments:
310  *
311  * Results:
312  *
313  * Side effects:
314  *
315  *--------------------------------------------------------------
316  */
317
318 gint
319 gdk_screen_width (void)
320 {
321   return gdk_display->modeinfo.xres;
322 }
323
324 /*
325  *--------------------------------------------------------------
326  * gdk_screen_height
327  *
328  *   Return the height of the screen.
329  *
330  * Arguments:
331  *
332  * Results:
333  *
334  * Side effects:
335  *
336  *--------------------------------------------------------------
337  */
338
339 gint
340 gdk_screen_height (void)
341 {
342   return gdk_display->modeinfo.yres;
343 }
344
345 /*
346  *--------------------------------------------------------------
347  * gdk_screen_width_mm
348  *
349  *   Return the width of the screen in millimeters.
350  *
351  * Arguments:
352  *
353  * Results:
354  *
355  * Side effects:
356  *
357  *--------------------------------------------------------------
358  */
359
360 gint
361 gdk_screen_width_mm (void)
362 {
363   return 0.5 + gdk_screen_width () * (25.4 / 72.);
364 }
365
366 /*
367  *--------------------------------------------------------------
368  * gdk_screen_height
369  *
370  *   Return the height of the screen in millimeters.
371  *
372  * Arguments:
373  *
374  * Results:
375  *
376  * Side effects:
377  *
378  *--------------------------------------------------------------
379  */
380
381 gint
382 gdk_screen_height_mm (void)
383 {
384   return 0.5 + gdk_screen_height () * (25.4 / 72.);
385 }
386
387 /*
388  *--------------------------------------------------------------
389  * gdk_set_sm_client_id
390  *
391  *   Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window
392  *   so that the window manager can save our state using the
393  *   X11R6 ICCCM session management protocol. A NULL value should 
394  *   be set following disconnection from the session manager to
395  *   remove the SM_CLIENT_ID property.
396  *
397  * Arguments:
398  * 
399  *   "sm_client_id" specifies the client id assigned to us by the
400  *   session manager or NULL to remove the property.
401  *
402  * Results:
403  *
404  * Side effects:
405  *
406  *--------------------------------------------------------------
407  */
408
409 void
410 gdk_set_sm_client_id (const gchar* sm_client_id)
411 {
412 }
413
414 void
415 gdk_key_repeat_disable (void)
416 {
417 }
418
419 void
420 gdk_key_repeat_restore (void)
421 {
422 }
423
424
425 void
426 gdk_beep (void)
427 {
428 }
429
430 extern void keyboard_shutdown(void);
431
432 void
433 gdk_windowing_exit (void)
434 {
435   gdk_fb_display_destroy(gdk_display); gdk_display = NULL;
436
437   gdk_fb_font_fini();
438
439   keyboard_shutdown();
440 }
441
442 gchar*
443 gdk_keyval_name (guint        keyval)
444 {
445   return NULL;
446 }
447
448 guint
449 gdk_keyval_from_name (const gchar *keyval_name)
450 {
451   return 0;
452 }
453
454 gchar *
455 gdk_get_display(void)
456 {
457   return g_strdup("/dev/fb0");
458 }
459
460 /* utils */
461 GdkEvent *
462 gdk_event_make(GdkWindow *window, GdkEventType type, gboolean append_to_queue)
463 {
464   static const guint type_masks[] = {
465     GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                = 0, */
466     GDK_STRUCTURE_MASK, /* GDK_DESTROY          = 1, */
467     GDK_EXPOSURE_MASK, /* GDK_EXPOSE            = 2, */
468     GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY       = 3, */
469     GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS  = 4, */
470     GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5, */
471     GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6, */
472     GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE      = 7, */
473     GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS        = 8, */
474     GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE    = 9, */
475     GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY  = 10, */
476     GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY  = 11, */
477     GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE  = 12, */
478     GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                = 13, */
479     GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP              = 14, */
480     GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP            = 15, */
481     GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY    = 16, */
482     GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR    = 17, */
483     GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18, */
484     GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY   = 19, */
485     GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN  = 20, */
486     GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT        = 21, */
487     GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER        = 22, */
488     GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE        = 23, */
489     GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION       = 24, */
490     GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS       = 25, */
491     GDK_ALL_EVENTS_MASK, /* GDK_DROP_START        = 26, */
492     GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED     = 27, */
493     GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT    = 28, */
494     GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29, */
495     GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE         = 30, */
496     GDK_SCROLL_MASK /* GDK_SCROLL            = 31 */
497   };
498   guint evmask;
499   evmask = GDK_WINDOW_IMPL_FBDATA(window)->event_mask;
500
501   if(evmask & GDK_BUTTON_MOTION_MASK)
502     {
503       evmask |= GDK_BUTTON1_MOTION_MASK|GDK_BUTTON2_MOTION_MASK|GDK_BUTTON3_MOTION_MASK;
504     }
505
506   if(evmask & (GDK_BUTTON1_MOTION_MASK|GDK_BUTTON2_MOTION_MASK|GDK_BUTTON3_MOTION_MASK))
507     {
508       gint x, y;
509       GdkModifierType mask;
510
511       gdk_input_ps2_get_mouseinfo(&x, &y, &mask);
512
513       if(((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK))
514          || ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK))
515          || ((mask & GDK_BUTTON3_MASK) && (evmask & GDK_BUTTON3_MOTION_MASK)))
516         evmask |= GDK_POINTER_MOTION_MASK;
517     }
518
519   if(evmask & type_masks[type])
520     {
521       GdkEvent *event = gdk_event_new();
522       guint32 the_time = g_latest_time.tv_sec * 1000 + g_latest_time.tv_usec / 1000;
523
524       event->any.type = type;
525       event->any.window = gdk_window_ref(window);
526       event->any.send_event = FALSE;
527       switch(type)
528         {
529         case GDK_MOTION_NOTIFY:
530           event->motion.time = the_time;
531           event->motion.axes = NULL;
532           break;
533         case GDK_BUTTON_PRESS:
534         case GDK_2BUTTON_PRESS:
535         case GDK_3BUTTON_PRESS:
536         case GDK_BUTTON_RELEASE:
537           event->button.time = the_time;
538           event->button.axes = NULL;
539           break;
540         case GDK_KEY_PRESS:
541         case GDK_KEY_RELEASE:
542           event->key.time = the_time;
543           break;
544         case GDK_ENTER_NOTIFY:
545         case GDK_LEAVE_NOTIFY:
546           event->crossing.time = the_time;
547           break;
548
549         case GDK_PROPERTY_NOTIFY:
550           event->property.time = the_time;
551           break;
552
553         case GDK_SELECTION_CLEAR:
554         case GDK_SELECTION_REQUEST:
555         case GDK_SELECTION_NOTIFY:
556           event->selection.time = the_time;
557           break;
558         case GDK_PROXIMITY_IN:
559         case GDK_PROXIMITY_OUT:
560           event->proximity.time = the_time;
561           break;
562         case GDK_DRAG_ENTER:
563         case GDK_DRAG_LEAVE:
564         case GDK_DRAG_MOTION:
565         case GDK_DRAG_STATUS:
566         case GDK_DROP_START:
567         case GDK_DROP_FINISHED:
568           event->dnd.time = the_time;
569           break;
570
571         case GDK_FOCUS_CHANGE:
572         case GDK_CONFIGURE:
573         case GDK_MAP:
574         case GDK_UNMAP:
575         case GDK_CLIENT_EVENT:
576         case GDK_VISIBILITY_NOTIFY:
577         case GDK_NO_EXPOSE:
578         case GDK_SCROLL:
579         case GDK_DELETE:
580         case GDK_DESTROY:
581         case GDK_EXPOSE:
582         default:
583           break;
584         }
585
586       if(append_to_queue)
587         gdk_event_queue_append(event);
588
589       return event;
590     }
591
592   return NULL;
593 }
594
595 void CM(void)
596 {
597   static gpointer mymem = NULL;
598   gpointer arry[256];
599   int i;
600
601   return;
602
603   free(mymem);
604
605   for(i = 0; i < sizeof(arry)/sizeof(arry[0]); i++)
606     arry[i] = malloc(i+1);
607   for(i = 0; i < sizeof(arry)/sizeof(arry[0]); i++)
608     free(arry[i]);
609
610   mymem = malloc(256);
611 }
612
613 /* XXX badhack */
614 typedef struct _GdkWindowPaint GdkWindowPaint;
615
616 struct _GdkWindowPaint
617 {
618   GdkRegion *region;
619   GdkPixmap *pixmap;
620   gint x_offset;
621   gint y_offset;
622 };
623
624 void RP(GdkDrawable *d)
625 {
626 #if 0
627   if(GDK_DRAWABLE_TYPE(d) == GDK_DRAWABLE_PIXMAP)
628     {
629       if(!GDK_PIXMAP_FBDATA(d)->no_free_mem)
630         {
631           guchar *oldmem = GDK_DRAWABLE_FBDATA(d)->mem;
632           guint len = ((GDK_DRAWABLE_IMPL_FBDATA(d)->width * GDK_DRAWABLE_IMPL_FBDATA(d)->depth + 7) / 8) * GDK_DRAWABLE_IMPL_FBDATA(d)->height;
633           GDK_DRAWABLE_IMPL_FBDATA(d)->mem = g_malloc(len);
634           memcpy(GDK_DRAWABLE_IMPL_FBDATA(d)->mem, oldmem, len);
635           g_free(oldmem);
636         }
637     }
638   else
639     {
640       GSList *priv = GDK_WINDOW_P(d)->paint_stack;
641       for(; priv; priv = priv->next)
642         {
643           GdkWindowPaint *p = priv->data;
644
645           RP(p->pixmap);
646         }
647     }
648 #endif
649 }