All pastes #1426916 Raw Edit

vanRijn - Compiz _NET_WM_FULLSCR

public cpp v1 · immutable
#1426916 ·published 2009-05-18 22:22 UTC
rendered paste body
/* * Simple program to demonstrate 2 bugs with Compiz 0.8.2 and programs that use * _NET_WM_FULLSCREEN_MONITORS. This program will present a simple window with a * button and a label. The label will display a textual explanation of what * topology the window should be covering. The button allows the user to click * it and cycle through the 6 topologies over 2 monitors. * * The bugs this demonstrates are as follows: * 1) When an application requests a topology change via *    _NET_WM_FULLSCREEN_MONITORS, Compiz does honor the topology change, but it *    does not refresh any monitor that has changed since the last *    _NET_WM_FULLSCREEN_MONITORS topology. If the application requests to *    change from fullscreening monitor 1 to cover both monitors 1 and 2, the *    window is resized and can still be interacted with, but the display still *    shows a frozen image of what was previously on the second monitor, for *    example. * * 2) When a window has fullscreened and used _NET_WM_FULLSCREEN_MONITORS, if *    any tooltips are used in that window (as this simple application does), *    Compiz will cause the screen to flash repeatedly until the user stops *    hovering over the originating widget and the tooltip goes away. This can *    be demonstrated in this simple application by hovering over the button in *    the window. As an interesting aside, when Compiz causes the screen to *    flash, it will refresh the monitors that were previously stale from #1 *    above. * * This program can be compiled like this: * *    gcc -Wall -g test_NET_WM_FULLSCREEN_MONITORS-wtf.c -o \ *    test_NET_WM_FULLSCREEN_MONITORS `pkg-config --cflags gtk+-2.0` `pkg-config \ *    --libs gtk+-2.0` */#include <gtk/gtk.h>#include <gdk/gdkx.h>#include <string.h>static GtkWidget* window;static GtkWidget* button;static GtkWidget* label;static guint topology;static gboolean fullscreen(){   gtk_window_fullscreen(GTK_WINDOW(window));   return FALSE;}static gboolean unfullscreen(){   gtk_window_unfullscreen(GTK_WINDOW(window));   return FALSE;}static gboolean switch_monitors(gpointer data){   static const long monitors[6][4] = {      {0, 0, 0, 0},      {1, 1, 1, 1},      {0, 1, 0, 0},      {1, 1, 0, 0},      {0, 0, 0, 1},      {0, 1, 0, 1}   };   static const char* desc[6] = {       "Window should be covering just the first head, height: top/bottom of first head\n",       "Window should be covering just the second head, height: top/bottom of second head\n",       "Window should be covering just the first head, height: top of first head, bottom of second head\n",       "Window should be covering just the first head, height: top of second head, bottom of second head\n",       "Window should be covering both heads 1 and 2, height: top and bottom of first head\n",       "Window should be covering both heads 1 and 2, height: top of first head, bottom of second head\n",   };   guint index = GPOINTER_TO_UINT(data);   g_debug("index: %d\n", index);   if (index > 5) {      unfullscreen();      gtk_label_set_text(GTK_LABEL(label), "Unfullscreened.");      topology = 0;      return FALSE;   } else {      fullscreen();      gtk_label_set_text(GTK_LABEL(label), desc[index]);   }   g_debug(desc[index]);   GdkDisplay *display = gdk_display_get_default();   XClientMessageEvent xclient;   memset(&xclient, 0, sizeof(xclient));   xclient.type = ClientMessage;   xclient.window = GDK_WINDOW_XID(window->window);   xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_FULLSCREEN_MONITORS");   xclient.format = 32;   xclient.data.l[0] = monitors[index][0];   xclient.data.l[1] = monitors[index][1];   xclient.data.l[2] = monitors[index][2];   xclient.data.l[3] = monitors[index][3];   xclient.data.l[4] = 1;   XSendEvent(GDK_WINDOW_XDISPLAY(window->window),              GDK_WINDOW_XWINDOW(gdk_get_default_root_window()),              False,              SubstructureRedirectMask | SubstructureNotifyMask,              (XEvent *) &xclient);   return FALSE;}static void close(GtkWidget *widget,                  gpointer   data ){    gtk_main_quit ();}static void clicked(GtkWidget *widget,		    gpointer   data ){   switch_monitors(GUINT_TO_POINTER(topology++));}int main(int argc, char** argv){   gtk_init(&argc, &argv);   GtkWidget* box;   topology = 0;   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);   g_signal_connect(G_OBJECT(window), "delete_event",		    G_CALLBACK(close), NULL);   g_signal_connect(G_OBJECT (window), "destroy",		    G_CALLBACK (close), NULL);   gtk_container_set_border_width (GTK_CONTAINER (window), 10);   button = gtk_button_new_with_label ("Push Me to change topologies!");   gtk_widget_show(button);   g_signal_connect(G_OBJECT (button), "clicked",		    G_CALLBACK (clicked), NULL);   label = gtk_label_new("I'll tell you what topology you're in here.");   gtk_widget_show(label);   box = gtk_vbox_new(FALSE, 10);   gtk_widget_show(box);   gtk_container_add(GTK_CONTAINER(window), box);   gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0);   gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);   gtk_widget_set_tooltip_text(GTK_WIDGET(button), "This is a tooltip!");   gtk_widget_show(window);   gtk_main();   return 0;}