GdkWindow * create_gdk_window (Window xframe) { GdkDisplay *display = gdk_display_get_default (); GdkScreen *screen = gdk_display_get_default_screen (display); GdkWindow *window = create_foreign_window (xframe); GdkColormap *cmap = gdk_screen_get_rgb_colormap (screen); gdk_drawable_set_colormap (GDK_DRAWABLE (window), cmap); return window; }
GdkFilterReturn event_filter_func (GdkXEvent *gdkxevent, GdkEvent *event, gpointer data) { GdkDisplay *gdkdisplay; XEvent *xevent = gdkxevent; gulong xid = 0; Window select = 0; gdkdisplay = gdk_display_get_default (); switch (xevent->type) { case CreateNotify: { if (!wnck_window_get (xevent->xcreatewindow.window)) { GdkWindow *toplevel = create_foreign_window (xevent->xcreatewindow.window); if (toplevel) { gdk_window_set_events (toplevel, gdk_window_get_events (toplevel) | GDK_PROPERTY_CHANGE_MASK); /* check if the window is a switcher and update accordingly */ if (get_window_prop (xevent->xcreatewindow.window, select_window_atom, &select)) update_switcher_window (xevent->xcreatewindow.window, select); } } } break; case ButtonPress: case ButtonRelease: xid = (gulong) g_hash_table_lookup (frame_table, GINT_TO_POINTER (xevent->xbutton.window)); break; case EnterNotify: case LeaveNotify: xid = (gulong) g_hash_table_lookup (frame_table, GINT_TO_POINTER (xevent->xcrossing.window)); break; case MotionNotify: xid = (gulong) g_hash_table_lookup (frame_table, GINT_TO_POINTER (xevent->xmotion.window)); break; case PropertyNotify: if (xevent->xproperty.atom == frame_input_window_atom) { WnckWindow *win; xid = xevent->xproperty.window; win = wnck_window_get (xid); if (win) { Window frame; if (!get_window_prop (xid, select_window_atom, &select)) { if (get_window_prop (xid, frame_input_window_atom, &frame)) add_frame_window (win, frame, FALSE); else remove_frame_window (win); } } } if (xevent->xproperty.atom == frame_output_window_atom) { WnckWindow *win; xid = xevent->xproperty.window; win = wnck_window_get (xid); if (win) { Window frame; if (!get_window_prop (xid, select_window_atom, &select)) { if (get_window_prop (xid, frame_output_window_atom, &frame)) add_frame_window (win, frame, TRUE); else remove_frame_window (win); } } } else if (xevent->xproperty.atom == compiz_shadow_info_atom || xevent->xproperty.atom == compiz_shadow_color_atom) { GdkScreen *g_screen = gdk_display_get_default_screen (gdkdisplay); Window root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (g_screen)); WnckScreen *screen; screen = wnck_screen_get_for_root (root); if (screen) { if (gwd_process_decor_shadow_property_update ()) decorations_changed (screen); } } else if (xevent->xproperty.atom == mwm_hints_atom) { WnckWindow *win; xid = xevent->xproperty.window; win = wnck_window_get (xid); if (win) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); gboolean decorated = FALSE; /* Only decorations that are actually bound to windows can be decorated * ignore cases where a broken application which shouldn't be decorated * sets the decoration hint */ if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE) && d->win) decorated = TRUE; if (decorated != d->decorated) { d->decorated = decorated; if (decorated) { d->context = NULL; d->width = d->height = 0; d->frame = gwd_get_decor_frame (get_frame_type (win)); update_window_decoration_state (win); update_window_decoration_actions (win); update_window_decoration_icon (win); request_update_window_decoration_size (win); update_event_windows (win); } else { remove_frame_window (win); } } } } else if (xevent->xproperty.atom == select_window_atom) { Window select; if (get_window_prop (xevent->xproperty.window, select_window_atom, &select)) update_switcher_window (xevent->xproperty.window, select); } break; case DestroyNotify: g_hash_table_remove (frame_table, GINT_TO_POINTER (xevent->xproperty.window)); break; case ClientMessage: if (xevent->xclient.message_type == toolkit_action_atom) { long action; action = xevent->xclient.data.l[0]; if (action == toolkit_action_window_menu_atom) { WnckWindow *win; win = wnck_window_get (xevent->xclient.window); if (win) { action_menu_map (win, xevent->xclient.data.l[2], xevent->xclient.data.l[1]); } } else if (action == toolkit_action_force_quit_dialog_atom) { WnckWindow *win; win = wnck_window_get (xevent->xclient.window); if (win) { if (xevent->xclient.data.l[2]) show_force_quit_dialog (win, xevent->xclient.data.l[1]); else hide_force_quit_dialog (win); } } } else if (xevent->xclient.message_type == decor_request_atom) { WnckWindow *win = wnck_window_get (xevent->xclient.window); if (win) update_window_decoration_size (win); } default: break; } if (xid) { WnckWindow *win; win = wnck_window_get (xid); if (win) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); if (d->decorated) { gint i, j; event_callback cb = NULL; Window w = xevent->xany.window; for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) if (d->event_windows[i][j].window == w) cb = d->event_windows[i][j].callback; if (!cb) { for (i = 0; i < BUTTON_NUM; ++i) if (d->button_windows[i].window == w) cb = d->button_windows[i].callback; } if (cb) { decor_event gtkwd_event; decor_event_type gtkwd_type; gtkwd_event.window = w; switch (xevent->type) { case ButtonPress: case ButtonRelease: if (xevent->type == ButtonPress) gtkwd_type = GButtonPress; else gtkwd_type = GButtonRelease; gtkwd_event.button = xevent->xbutton.button; gtkwd_event.x = xevent->xbutton.x; gtkwd_event.y = xevent->xbutton.y; gtkwd_event.x_root = xevent->xbutton.x_root; gtkwd_event.y_root = xevent->xbutton.y_root; gtkwd_event.time = xevent->xbutton.time; break; case EnterNotify: case LeaveNotify: if (xevent->type == EnterNotify) gtkwd_type = GEnterNotify; else gtkwd_type = GLeaveNotify; gtkwd_event.x = xevent->xcrossing.x; gtkwd_event.y = xevent->xcrossing.y; gtkwd_event.x_root = xevent->xcrossing.x_root; gtkwd_event.y_root = xevent->xcrossing.y_root; gtkwd_event.time = xevent->xcrossing.time; break; default: cb = NULL; break; } if (cb) (*cb) (win, >kwd_event, gtkwd_type); } } } } return GDK_FILTER_CONTINUE; }
int main (int argc, char *argv[]) { GdkDisplay *gdkdisplay; Display *xdisplay; GdkScreen *gdkscreen; WnckScreen *screen; gint i, j, status; gboolean replace = FALSE; unsigned int nchildren; Window root_ret, parent_ret; Window *children = NULL; GList *windows, *win; decor_frame_t *bare_p, *switcher_p; const char *option_meta_theme = NULL; gint option_blur_type = 0; program_name = argv[0]; gtk_init (&argc, &argv); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--minimal") == 0) { minimal = TRUE; } else if (strcmp (argv[i], "--replace") == 0) { replace = TRUE; } else if (strcmp (argv[i], "--blur") == 0) { if (argc > ++i) { if (strcmp (argv[i], "titlebar") == 0) option_blur_type = BLUR_TYPE_TITLEBAR; else if (strcmp (argv[i], "all") == 0) option_blur_type = BLUR_TYPE_ALL; } } #ifdef USE_METACITY else if (strcmp (argv[i], "--metacity-theme") == 0) { if (argc > ++i) option_meta_theme = argv[i]; } #endif else if (strcmp (argv[i], "--help") == 0) { fprintf (stderr, "%s " "[--minimal] " "[--replace] " "[--blur none|titlebar|all] " #ifdef USE_METACITY "[--metacity-theme THEME] " #endif "[--help]" "\n", program_name); return 0; } } gdkdisplay = gdk_display_get_default (); xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay); gdkscreen = gdk_display_get_default_screen (gdkdisplay); frame_input_window_atom = XInternAtom (xdisplay, DECOR_INPUT_FRAME_ATOM_NAME, FALSE); frame_output_window_atom = XInternAtom (xdisplay, DECOR_OUTPUT_FRAME_ATOM_NAME, FALSE); win_decor_atom = XInternAtom (xdisplay, DECOR_WINDOW_ATOM_NAME, FALSE); win_blur_decor_atom = XInternAtom (xdisplay, DECOR_BLUR_ATOM_NAME, FALSE); wm_move_resize_atom = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", FALSE); restack_window_atom = XInternAtom (xdisplay, "_NET_RESTACK_WINDOW", FALSE); select_window_atom = XInternAtom (xdisplay, DECOR_SWITCH_WINDOW_ATOM_NAME, FALSE); mwm_hints_atom = XInternAtom (xdisplay, "_MOTIF_WM_HINTS", FALSE); switcher_fg_atom = XInternAtom (xdisplay, DECOR_SWITCH_FOREGROUND_COLOR_ATOM_NAME, FALSE); compiz_shadow_info_atom = XInternAtom (xdisplay, "_COMPIZ_NET_CM_SHADOW_PROPERTIES", FALSE); compiz_shadow_color_atom = XInternAtom (xdisplay, "_COMPIZ_NET_CM_SHADOW_COLOR", FALSE); toolkit_action_atom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION", FALSE); toolkit_action_window_menu_atom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_WINDOW_MENU", FALSE); toolkit_action_force_quit_dialog_atom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_FORCE_QUIT_DIALOG", FALSE); net_wm_state_atom = XInternAtom (xdisplay,"_NET_WM_STATE", 0); net_wm_state_modal_atom = XInternAtom (xdisplay, "_NET_WM_STATE_MODAL", 0); decor_request_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_REQUEST", 0); decor_pending_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_PENDING", 0); decor_delete_pixmap_atom = XInternAtom (xdisplay, "_COMPIZ_DECOR_DELETE_PIXMAP", 0); status = decor_acquire_dm_session (xdisplay, gdk_screen_get_number (gdkscreen), "gwd", replace, &dm_sn_timestamp); if (status != DECOR_ACQUIRE_STATUS_SUCCESS) { if (status == DECOR_ACQUIRE_STATUS_FAILED) { fprintf (stderr, "%s: Could not acquire decoration manager " "selection on screen %d display \"%s\"\n", program_name, gdk_screen_get_number (gdkscreen), DisplayString (xdisplay)); } else if (status == DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING) { fprintf (stderr, "%s: Screen %d on display \"%s\" already " "has a decoration manager; try using the " "--replace option to replace the current " "decoration manager.\n", program_name, gdk_screen_get_number (gdkscreen), DisplayString (xdisplay)); } return 1; } screen = wnck_screen_get_default (); initialize_decorations (); notified = gwd_settings_notified_impl_new (screen); if (!notified) return 1; writable = GWD_SETTINGS_WRITABLE_INTERFACE (gwd_settings_impl_new (option_blur_type != BLUR_TYPE_NONE ? &option_blur_type : NULL, option_meta_theme ? &option_meta_theme : NULL, notified)); if (!writable) { g_object_unref (notified); return 1; } settings = GWD_SETTINGS_INTERFACE (writable); gwd_settings_writable_freeze_updates (writable); if (!init_settings (writable, screen)) { g_object_unref (writable); fprintf (stderr, "%s: Failed to get necessary gtk settings\n", argv[0]); return 1; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { if (cursor[i][j].shape != XC_left_ptr) cursor[i][j].cursor = XCreateFontCursor (xdisplay, cursor[i][j].shape); } } xformat_rgba = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); xformat_rgb = XRenderFindStandardFormat (xdisplay, PictStandardRGB24); frame_table = g_hash_table_new (NULL, NULL); destroyed_pixmaps_table = g_hash_table_new (NULL, NULL); if (!create_tooltip_window ()) { g_object_unref (writable); free (settings); fprintf (stderr, "%s, Couldn't create tooltip window\n", argv[0]); return 1; } wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER); gdk_window_add_filter (NULL, selection_event_filter_func, NULL); if (!minimal) { GdkWindow *root = create_foreign_window (gdk_x11_get_default_root_xwindow ()); gdk_window_add_filter (NULL, event_filter_func, NULL); XQueryTree (xdisplay, gdk_x11_get_default_root_xwindow (), &root_ret, &parent_ret, &children, &nchildren); for (i = 0; i < nchildren; i++) { GdkWindow *toplevel = create_foreign_window (children[i]); /* Need property notify on all windows */ gdk_window_set_events (toplevel, gdk_window_get_events (toplevel) | GDK_PROPERTY_CHANGE_MASK); } /* Need MapNotify on new windows */ gdk_window_set_events (root, gdk_window_get_events (root) | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_SUBSTRUCTURE_MASK); connect_screen (screen); } decor_set_dm_check_hint (xdisplay, gdk_screen_get_number (gdkscreen), WINDOW_DECORATION_TYPE_PIXMAP | WINDOW_DECORATION_TYPE_WINDOW); /* Update the decorations based on the settings */ gwd_settings_writable_thaw_updates (writable); /* Keep the default, bare and switcher decorations around * since otherwise they will be spuriously recreated */ bare_p = gwd_get_decor_frame ("bare"); switcher_p = gwd_get_decor_frame ("switcher"); update_default_decorations (gdkscreen); gtk_main (); win = windows = wnck_screen_get_windows (screen); while (win != NULL) { WnckWindow *w = (WnckWindow *) win->data; window_closed (screen, w); win = g_list_next (win); } g_list_free (windows); if (tip_label) gtk_widget_destroy (GTK_WIDGET (tip_label)); if (tip_window) gtk_widget_destroy (GTK_WIDGET (tip_window)); gwd_decor_frame_unref (bare_p); gwd_decor_frame_unref (switcher_p); fini_settings (); return 0; }