📄 gdkwindow-fb.c
字号:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <config.h>#include "gdk.h"#include "gdkwindow.h"#include "gdkinputprivate.h"#include "gdkprivate-fb.h"#include "gdkinternals.h"#include <limits.h>/* Global variables: */static GdkWindow *gdk_fb_window_containing_pointer = NULL;static GdkWindow *gdk_fb_focused_window = NULL;static gpointer parent_class = NULL;static void recompute_drawable (GdkDrawable *drawable);static void gdk_fb_window_raise (GdkWindow *window);static GdkRegion* gdk_window_fb_get_visible_region (GdkDrawable *drawable);typedef struct{ GdkWindowChildChanged changed; GdkWindowChildGetPos get_pos; gpointer user_data;} GdkWindowChildHandlerData;static voidg_free_2nd (gpointer a, gpointer b, gpointer data){ g_free (b);}static voidgdk_window_impl_fb_finalize (GObject *object){ GdkWindowFBData *fbd = GDK_WINDOW_FBDATA (object); if (GDK_WINDOW_IS_MAPPED (fbd->drawable_data.wrapper)) gdk_window_hide (fbd->drawable_data.wrapper); if (fbd->cursor) gdk_cursor_unref (fbd->cursor); if (fbd->properties) { g_hash_table_foreach (fbd->properties, g_free_2nd, NULL); g_hash_table_destroy (fbd->properties); } G_OBJECT_CLASS (parent_class)->finalize (object);}static voidgdk_window_impl_fb_class_init (GdkWindowFBClass *klass){ GObjectClass *object_class = G_OBJECT_CLASS (klass); GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gdk_window_impl_fb_finalize; /* Visible and clip regions are the same */ drawable_class->get_clip_region = gdk_window_fb_get_visible_region; drawable_class->get_visible_region = gdk_window_fb_get_visible_region;}static voidgdk_window_impl_fb_init (GdkWindowFBData *impl){ impl->drawable_data.depth = gdk_display->modeinfo.bits_per_pixel; impl->drawable_data.colormap = gdk_colormap_get_system (); impl->shape = NULL;}GType_gdk_window_impl_get_type (void){ static GType object_type = 0; if (!object_type) { static const GTypeInfo object_info = { sizeof (GdkWindowFBClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gdk_window_impl_fb_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GdkWindowFBData), 0, /* n_preallocs */ (GInstanceInitFunc) gdk_window_impl_fb_init, }; object_type = g_type_register_static (gdk_drawable_impl_fb_get_type(), "GdkWindowFB", &object_info, 0); } return object_type;}void_gdk_windowing_window_init (void){ GdkWindowAttr attr; GdkCursor *cursor; GdkWindowObject *private; attr.width = gdk_screen_width (); attr.height = gdk_screen_height (); attr.window_type = GDK_WINDOW_ROOT; attr.cursor = NULL; attr.event_mask = GDK_EXPOSURE_MASK; attr.wclass = GDK_INPUT_OUTPUT; _gdk_parent_root = gdk_window_new (NULL, &attr, GDK_WA_CURSOR); private = (GdkWindowObject *)_gdk_parent_root; private->state = 0; GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->lim_x = attr.width; GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->lim_y = attr.height; _gdk_fb_screen_gc = gdk_gc_new (_gdk_parent_root); gdk_fb_drawable_clear (_gdk_parent_root); /* Must be done after root is created, since gdk_cursor_new() * references _gdk_parent_root. */ cursor = gdk_cursor_new (GDK_LEFT_PTR); gdk_window_set_cursor (_gdk_parent_root, cursor);}GdkWindow*gdk_window_new (GdkWindow *parent, GdkWindowAttr *attributes, gint attributes_mask){ GdkWindow *window; GdkWindowObject *private; GdkWindowObject *parent_private; GdkVisual *visual; GdkWindowFBData *impl; int x, y, depth; g_return_val_if_fail (attributes != NULL, NULL); if (!parent || (attributes->window_type != GDK_WINDOW_CHILD && attributes->window_type != GDK_WINDOW_TEMP)) parent = _gdk_parent_root; parent_private = (GdkWindowObject*) parent; window = (GdkWindow *)g_object_new (GDK_TYPE_WINDOW, NULL); private = (GdkWindowObject *)window; private->parent = parent_private; private->accept_focus = TRUE; private->focus_on_map = TRUE; if (attributes_mask & GDK_WA_X) x = attributes->x; else x = 0; if (attributes_mask & GDK_WA_Y) y = attributes->y; else y = 0; gdk_window_set_events (window, attributes->event_mask); if (attributes_mask & GDK_WA_VISUAL) visual = attributes->visual; else visual = gdk_visual_get_system (); impl = (GdkWindowFBData *)private->impl; impl->drawable_data.wrapper = window; private->x = x; private->y = y; impl->drawable_data.width = (attributes->width > 1) ? (attributes->width) : (1); impl->drawable_data.height = (attributes->height > 1) ? (attributes->height) : (1); private->window_type = impl->drawable_data.window_type = attributes->window_type; impl->drawable_data.mem = gdk_display->fb_mem; impl->drawable_data.rowstride = gdk_display->fb_stride; gdk_window_move_resize (window, x, y, impl->drawable_data.width, impl->drawable_data.height); if (attributes->wclass == GDK_INPUT_OUTPUT) { depth = visual->depth; private->input_only = FALSE; private->depth = impl->drawable_data.depth; if ((attributes_mask & GDK_WA_COLORMAP) && attributes->colormap) impl->drawable_data.colormap = attributes->colormap; else impl->drawable_data.colormap = gdk_colormap_get_system (); switch (impl->drawable_data.window_type) { case GDK_WINDOW_TOPLEVEL: case GDK_WINDOW_CHILD: case GDK_WINDOW_DIALOG: case GDK_WINDOW_TEMP: default: break; case GDK_WINDOW_ROOT: if (_gdk_parent_root) g_error ("cannot make windows of type GDK_WINDOW_ROOT"); break; case GDK_DRAWABLE_PIXMAP: g_error ("cannot make windows of type GDK_DRAWABLE_PIXMAP (use gdk_pixmap_new)"); break; } } else { depth = 0; private->input_only = TRUE; impl->drawable_data.colormap = NULL; } if (impl->drawable_data.colormap) gdk_colormap_ref (impl->drawable_data.colormap); gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ? (attributes->cursor) : NULL)); if (parent_private) parent_private->children = g_list_prepend (parent_private->children, window); return window;}/* This function is called when the XWindow is really gone. */void_gdk_windowing_window_destroy (GdkWindow *window, gboolean recursing, gboolean foreign_destroy){ GdkWindowObject *private; GdkRectangle r; private = (GdkWindowObject*) window; _gdk_selection_window_destroyed (window); r.x = private->x; r.y = private->y; r.width = GDK_DRAWABLE_IMPL_FBDATA (window)->width; r.height = GDK_DRAWABLE_IMPL_FBDATA (window)->height; /* Clear the root window, as it might be visible under the destroyed window */ gdk_window_clear_area (_gdk_parent_root, r.x, r.y, r.width, r.height); /* Invalidate the rect */ gdk_window_invalidate_rect ((GdkWindow *)private->parent, &r, TRUE);}static gbooleanall_parents_shown (GdkWindowObject *private){ while (GDK_WINDOW_IS_MAPPED (private)) { if (private->parent) private = (GdkWindowObject *)private->parent; else return TRUE; } return FALSE;}static voidsend_map_events (GdkWindowObject *private, gboolean is_map){ GList *l; GdkWindow *parent = (GdkWindow *)private->parent; GdkWindow *event_win; g_assert (is_map); if (!GDK_WINDOW_IS_MAPPED (private)) return; if (is_map) { event_win = gdk_fb_other_event_window ((GdkWindow *)private, GDK_MAP); if (event_win) gdk_event_make (event_win, GDK_MAP, TRUE); } if (private->input_only) return; if (!parent) parent = (GdkWindow *)private; if (((GDK_DRAWABLE_IMPL_FBDATA (private)->abs_x > GDK_DRAWABLE_IMPL_FBDATA (parent)->lim_x) || (GDK_DRAWABLE_IMPL_FBDATA (private)->abs_y > GDK_DRAWABLE_IMPL_FBDATA (parent)->lim_y) || (GDK_DRAWABLE_IMPL_FBDATA (private)->lim_x < GDK_DRAWABLE_IMPL_FBDATA (parent)->llim_x) || (GDK_DRAWABLE_IMPL_FBDATA (private)->lim_y < GDK_DRAWABLE_IMPL_FBDATA (parent)->llim_y))) return; if (is_map) gdk_window_clear ((GdkWindow *)private); for (l = private->children; l; l = l->next) send_map_events (l->data, is_map);}/* Cut & paste versions of the stuff in gdkwindow.c, with the addition of clearing the newly exposed region. */voidgdk_window_invalidate_region_clear(GdkWindow *window, GdkRegion *region){ int i; GdkWindowObject *private = GDK_WINDOW_P (window); if (private->input_only || !GDK_WINDOW_IS_MAPPED (private)) return; if (private->bg_pixmap != GDK_NO_BG) for (i = 0; i < region->numRects; i++) gdk_window_clear_area (window, region->rects[i].x1, region->rects[i].y1, region->rects[i].x2 - region->rects[i].x1, region->rects[i].y2 - region->rects[i].y1); gdk_window_invalidate_region (window, region, FALSE); { GList *tmp_list; GdkRectangle child_rect; GdkRegion *child_region; tmp_list = private->children; while (tmp_list) { GdkWindowObject *child = tmp_list->data; tmp_list = tmp_list->next; if (!child->input_only) { gint width, height; gdk_drawable_get_size (GDK_DRAWABLE (child), &width, &height); child_rect.x = child->x; child_rect.y = child->y; child_rect.width = width; child_rect.height = height; child_region = gdk_region_rectangle (&child_rect); gdk_region_intersect (child_region, region); if (!gdk_region_empty (child_region)) { gdk_region_offset (child_region, - child_rect.x, - child_rect.y); gdk_window_invalidate_region_clear ((GdkWindow *)child, child_region); } gdk_region_destroy (child_region); } } } }voidgdk_window_invalidate_rect_clear (GdkWindow *window, GdkRectangle *rect){ GdkWindowObject *private = GDK_WINDOW_P (window); if (private->input_only || !GDK_WINDOW_IS_MAPPED (private)) return; if (GDK_WINDOW_P (window)->bg_pixmap != GDK_NO_BG) gdk_window_clear_area (window, rect->x, rect->y, rect->width, rect->height); gdk_window_invalidate_rect (window, rect, FALSE); { GList *tmp_list; GdkRectangle child_rect, new_rect; tmp_list = private->children; while (tmp_list) { GdkWindowObject *child = tmp_list->data; tmp_list = tmp_list->next; if (!child->input_only) { gint width, height; width = GDK_DRAWABLE_IMPL_FBDATA (child)->width; height = GDK_DRAWABLE_IMPL_FBDATA (child)->height; child_rect.x = child->x; child_rect.y = child->y; child_rect.width = width; child_rect.height = height; if (gdk_rectangle_intersect (rect, &child_rect, &new_rect)) { new_rect.x -= child_rect.x; new_rect.y -= child_rect.y; gdk_window_invalidate_rect_clear ((GdkWindow *)child, &new_rect); } } } }}voidgdk_fb_redraw_all (void){ GdkRectangle r; r.x = r.y = 0; r.width = GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->width; r.height = GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->height; gdk_window_invalidate_rect_clear (_gdk_parent_root, &r); gdk_window_process_all_updates ();}/* Focus follows pointer */static GdkWindow *gdk_fb_window_find_toplevel (GdkWindow *window){ GdkWindowObject *priv = (GdkWindowObject *)window; while (priv != (GdkWindowObject *)_gdk_parent_root) { if ((priv->parent == (GdkWindowObject *)_gdk_parent_root) && GDK_WINDOW_IS_MAPPED (priv)) return (GdkWindow *)priv; priv = priv->parent; } return _gdk_parent_root;}GdkWindow *gdk_fb_window_find_focus (void){ if (_gdk_fb_keyboard_grab_window) return _gdk_fb_keyboard_grab_window; if (!gdk_fb_focused_window) gdk_fb_focused_window = gdk_window_ref (_gdk_parent_root); return gdk_fb_focused_window;}static voidgdk_fb_change_focus (GdkWindow *new_focus_window){ GdkEventFocus *event; GdkWindow *old_win, *new_win; GdkWindow *event_win; /* No focus changes while the pointer is grabbed */ if (_gdk_fb_pointer_grab_window) return; old_win = gdk_fb_focused_window; new_win = gdk_fb_window_find_toplevel (new_focus_window); if (old_win != new_win) { if (old_win) { event_win = gdk_fb_keyboard_event_window (old_win, GDK_FOCUS_CHANGE); if (event_win) { event = (GdkEventFocus *)gdk_event_make (event_win, GDK_FOCUS_CHANGE, TRUE); event->in = FALSE; } } event_win = gdk_fb_keyboard_event_window (new_win, GDK_FOCUS_CHANGE); if (event_win) { event = (GdkEventFocus *)gdk_event_make (event_win, GDK_FOCUS_CHANGE, TRUE); event->in = TRUE; } if (gdk_fb_focused_window) gdk_window_unref (gdk_fb_focused_window); gdk_fb_focused_window = gdk_window_ref (new_win); }}static GdkWindow *gdk_fb_find_common_ancestor (GdkWindow *win1, GdkWindow *win2){ GdkWindowObject *tmp; GList *path1 = NULL, *path2 = NULL; GList *list1, *list2; tmp = GDK_WINDOW_OBJECT (win1); while (tmp) { path1 = g_list_prepend(path1, tmp); tmp = tmp->parent; } tmp = GDK_WINDOW_OBJECT (win2); while (tmp) { path2 = g_list_prepend(path2, tmp); tmp = tmp->parent; } list1 = path1; list2 = path2; tmp = NULL; while (list1 && list2 && (list1->data == list2->data)) { tmp = (GdkWindowObject *)list1->data; list1 = g_list_next (list1); list2 = g_list_next (list2); } g_list_free (path1); g_list_free (path2); return GDK_WINDOW (tmp);}voidgdk_fb_window_send_crossing_events (GdkWindow *src, GdkWindow *dest, GdkCrossingMode mode){ GdkWindow *c; GdkWindow *win, *last, *next; GdkEvent *event; gint x, y, x_int, y_int; GdkModifierType my_mask; GList *path, *list; gboolean non_linear; GdkWindow *a; GdkWindow *b; GdkWindow *event_win; if ((mode == GDK_CROSSING_NORMAL) && (dest == gdk_fb_window_containing_pointer)) return; if (gdk_fb_window_containing_pointer == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -