Example #1
0
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;
}
Example #2
0
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, &gtkwd_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;
}