diff --git a/src/core.c b/src/core.c index 72acfa199..330dfefe2 100644 --- a/src/core.c +++ b/src/core.c @@ -21,6 +21,7 @@ #include "core.h" #include "frame.h" +#include "workspace.h" void meta_core_get_frame_size (Display *xdisplay, @@ -234,3 +235,124 @@ meta_core_delete (Display *xdisplay, meta_window_delete (window, timestamp); } +void +meta_core_unshade (Display *xdisplay, + Window frame_xwindow) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_unshade (window); +} + +void +meta_core_shade (Display *xdisplay, + Window frame_xwindow) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_shade (window); +} + +void +meta_core_unstick (Display *xdisplay, + Window frame_xwindow) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_unstick (window); +} + +void +meta_core_stick (Display *xdisplay, + Window frame_xwindow) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_stick (window); +} + +void +meta_core_change_workspace (Display *xdisplay, + Window frame_xwindow, + int new_workspace) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_change_workspace (window, + meta_display_get_workspace_by_screen_index (display, + window->screen, + new_workspace)); +} + +int +meta_core_get_num_workspaces (Screen *xscreen) +{ + MetaScreen *screen; + + screen = meta_screen_for_x_screen (xscreen); + + return meta_screen_get_n_workspaces (screen); +} + +int +meta_core_get_active_workspace (Screen *xscreen) +{ + MetaScreen *screen; + + screen = meta_screen_for_x_screen (xscreen); + + return meta_workspace_screen_index (screen->active_workspace); +} + +int +meta_core_get_frame_workspace (Display *xdisplay, + Window frame_xwindow) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + return meta_window_get_net_wm_desktop (window); +} + + diff --git a/src/core.h b/src/core.h index 97cdfc50d..bf6bcdcab 100644 --- a/src/core.h +++ b/src/core.h @@ -85,10 +85,8 @@ void meta_core_change_workspace (Display *xdisplay, int new_workspace); -int meta_core_get_num_workspaces (Display *xdisplay, - Screen *xscreen); -int meta_core_get_active_workspace (Display *xdisplay, - Screen *xscreen); +int meta_core_get_num_workspaces (Screen *xscreen); +int meta_core_get_active_workspace (Screen *xscreen); int meta_core_get_frame_workspace (Display *xdisplay, Window frame_xwindow); diff --git a/src/display.c b/src/display.c index b71b48291..0cb399f8b 100644 --- a/src/display.c +++ b/src/display.c @@ -99,7 +99,7 @@ meta_display_open (const char *name) "WM_STATE", "_NET_CLOSE_WINDOW", "_NET_WM_STATE", - "MOTIF_WM_HINTS", + "_MOTIF_WM_HINTS", "_NET_WM_STATE_SHADED", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_MAXIMIZED_VERT", @@ -124,7 +124,8 @@ meta_display_open (const char *name) "_NET_CLIENT_LIST_STACKING", "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_SKIP_PAGER", - "_WIN_WORKSPACE" + "_WIN_WORKSPACE", + "_WIN_LAYER" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -198,6 +199,7 @@ meta_display_open (const char *name) display->atom_net_wm_state_skip_taskbar = atoms[30]; display->atom_net_wm_state_skip_pager = atoms[31]; display->atom_win_workspace = atoms[32]; + display->atom_win_layer = atoms[33]; /* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK, * created in screen_new diff --git a/src/display.h b/src/display.h index c7dadd618..6f2b24df5 100644 --- a/src/display.h +++ b/src/display.h @@ -89,6 +89,7 @@ struct _MetaDisplay Atom atom_net_wm_state_skip_taskbar; Atom atom_net_wm_state_skip_pager; Atom atom_win_workspace; + Atom atom_win_layer; /* This is the actual window from focus events, * not the one we last set diff --git a/src/errors.c b/src/errors.c index 85b678fb6..b3dad8353 100644 --- a/src/errors.c +++ b/src/errors.c @@ -64,6 +64,7 @@ meta_error_trap_pop (MetaDisplay *display) ErrorTrap *et; GSList *next; + XSync (display->xdisplay, False); return gdk_error_trap_pop (); /* below here is old method */ diff --git a/src/frames.c b/src/frames.c index 12a6df8e2..1b0f37e04 100644 --- a/src/frames.c +++ b/src/frames.c @@ -359,6 +359,20 @@ queue_recalc_func (gpointer key, gpointer value, gpointer data) gdk_window_invalidate_rect (frame->window, NULL, FALSE); meta_core_queue_frame_resize (gdk_display, frame->xwindow); + if (frame->layout) + { + /* recreate layout */ + char *text; + + text = g_strdup (pango_layout_get_text (frame->layout)); + + g_object_unref (G_OBJECT (frame->layout)); + + frame->layout = gtk_widget_create_pango_layout (GTK_WIDGET (frames), + text); + + g_free (text); + } } static void @@ -946,9 +960,6 @@ meta_frames_button_press_event (GtkWidget *widget, MetaFrameControl control; frames = META_FRAMES (widget); - - if (frames->grab_frame != NULL) - return FALSE; /* already up to something */ frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) @@ -956,6 +967,27 @@ meta_frames_button_press_event (GtkWidget *widget, control = get_control (frames, frame, event->x, event->y); + if (control == META_FRAME_CONTROL_TITLE && + event->button == 1 && + event->type == GDK_2BUTTON_PRESS) + { + MetaFrameFlags flags; + + flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); + + if (flags & META_FRAME_SHADED) + meta_core_unshade (gdk_display, + frame->xwindow); + else + meta_core_shade (gdk_display, + frame->xwindow); + + return TRUE; + } + + if (frames->grab_frame != NULL) + return FALSE; /* already up to something */ + if (event->button == 1) meta_core_user_raise (gdk_display, frame->xwindow); @@ -1006,7 +1038,7 @@ meta_frames_button_press_event (GtkWidget *widget, } } else if (control == META_FRAME_CONTROL_RESIZE_SE && - event->button == 1) + event->button == 1) { int w, h; diff --git a/src/frames.h b/src/frames.h index b81c64af6..d79c3057d 100644 --- a/src/frames.h +++ b/src/frames.h @@ -89,6 +89,8 @@ struct _MetaFrames int text_height; GHashTable *frames; + + GtkWidget *menu; /* The below is all for grabs */ MetaFrameStatus grab_status; @@ -130,4 +132,10 @@ void meta_frames_reset_bg (MetaFrames *frames, void meta_frames_queue_draw (MetaFrames *frames, Window xwindow); +void meta_frames_get_pixmap_for_control (MetaFrames *frames, + MetaFrameControl control, + GdkPixmap **pixmap, + GdkBitmap **mask); +void meta_frames_notify_menu_hide (MetaFrames *frames); + #endif diff --git a/src/menu.c b/src/menu.c index c8b51fc33..e6cb010a3 100644 --- a/src/menu.c +++ b/src/menu.c @@ -21,6 +21,8 @@ #include "menu.h" #include "main.h" +#include "util.h" +#include "core.h" typedef struct _MenuItem MenuItem; typedef struct _MenuData MenuData; @@ -48,23 +50,23 @@ struct _MenuItem struct _MenuData { - GdkWindow *window; - MetaMessageWindowMenuOps op; + MetaFrames *frames; + MetaUIFrame *frame; + MetaMenuOp op; }; static void activate_cb (GtkWidget *menuitem, gpointer data); -static GtkWidget *menu = NULL; static MenuItem menuitems[] = { - { META_MESSAGE_MENU_DELETE, GTK_STOCK_CLOSE, N_("_Close") }, - { META_MESSAGE_MENU_MINIMIZE, NULL, N_("_Minimize") }, - { META_MESSAGE_MENU_MAXIMIZE, NULL, N_("Ma_ximize") }, - { META_MESSAGE_MENU_UNMAXIMIZE, NULL, N_("_Unmaximize") }, - { META_MESSAGE_MENU_SHADE, NULL, N_("_Shade") }, - { META_MESSAGE_MENU_UNSHADE, NULL, N_("U_nshade") }, + { META_MENU_OP_DELETE, NULL, N_("_Close") }, + { META_MENU_OP_MINIMIZE, NULL, N_("_Minimize") }, + { META_MENU_OP_MAXIMIZE, NULL, N_("Ma_ximize") }, + { META_MENU_OP_UNMAXIMIZE, NULL, N_("_Unmaximize") }, + { META_MENU_OP_SHADE, NULL, N_("_Shade") }, + { META_MENU_OP_UNSHADE, NULL, N_("U_nshade") }, { 0, NULL, NULL }, /* separator */ - { META_MESSAGE_MENU_STICK, NULL, N_("Put on _All Workspaces") }, - { META_MESSAGE_MENU_UNSTICK, NULL, N_("Only on _This Workspace") } + { META_MENU_OP_STICK, NULL, N_("Put on _All Workspaces") }, + { META_MENU_OP_UNSTICK, NULL, N_("Only on _This Workspace") } }; static void @@ -89,121 +91,71 @@ popup_position_func (GtkMenu *menu, *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); } -static gint -get_num_desktops (void) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - int result; - - XGetWindowProperty (gdk_display, gdk_root_window, - gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); +static void +menu_closed (GtkMenu *menu, + gpointer data) +{ + MetaFrames *frames; - if (type != XA_CARDINAL) - return 0; + frames = META_FRAMES (data); - result = *num; - - XFree (num); + meta_frames_notify_menu_hide (frames); - return result; -} - -static gint -get_active_desktop (void) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - int result; - - XGetWindowProperty (gdk_display, gdk_root_window, - gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - - if (type != XA_CARDINAL) - return 0; - - result = *num; - - XFree (num); - - return result; -} - -static gulong -get_current_desktop (GdkWindow *window) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - gulong result; - int err; - - gdk_error_trap_push (); - type = None; - XGetWindowProperty (gdk_display, GDK_WINDOW_XID (window), - gdk_atom_intern ("_NET_WM_DESKTOP", FALSE), - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - err = gdk_error_trap_pop (); - if (err != Success) - meta_ui_warning ("Error %d getting _NET_WM_DESKTOP\n", err); - - if (type != XA_CARDINAL) - { - meta_ui_warning ("_NET_WM_DESKTOP has wrong type %s\n", gdk_atom_name (type)); - return 0xFFFFFFFF; /* sticky */ - } - - result = *num; - - XFree (num); - - return result; + gtk_widget_destroy (frames->menu); + frames->menu = NULL; } void -meta_window_menu_show (gulong xwindow, - int root_x, int root_y, - int button, - MetaMessageWindowMenuOps ops, - MetaMessageWindowMenuOps insensitive, - guint32 timestamp) +meta_window_menu_show (MetaFrames *frames, + MetaUIFrame *frame, + int root_x, + int root_y, + int button, + guint32 timestamp) { int i; - GdkWindow *window; GdkPoint *pt; int n_workspaces; int current_workspace; + MetaMenuOp ops; + MetaMenuOp insensitive; + MetaFrameFlags flags; - if (menu) - gtk_widget_destroy (menu); + flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); + + ops = 0; + insensitive = 0; + + if (flags & META_FRAME_ALLOWS_MAXIMIZE) + { + if (flags & META_FRAME_MAXIMIZED) + ops |= META_MENU_OP_UNMAXIMIZE; + else + ops |= META_MENU_OP_MAXIMIZE; + } - window = gdk_xid_table_lookup (xwindow); - if (window) - g_object_ref (G_OBJECT (window)); + if (flags & META_FRAME_SHADED) + ops |= META_MENU_OP_UNSHADE; else - window = gdk_window_foreign_new (xwindow); + ops |= META_MENU_OP_SHADE; - /* X error creating the foreign window means NULL here */ - if (window == NULL) - return; + if (flags & META_FRAME_STUCK) + ops |= META_MENU_OP_UNSTICK; + else + ops |= META_MENU_OP_STICK; - menu = gtk_menu_new (); + ops |= (META_MENU_OP_DELETE | META_MENU_OP_WORKSPACES | META_MENU_OP_MINIMIZE); + + if (!(flags & META_FRAME_ALLOWS_MINIMIZE)) + insensitive |= META_MENU_OP_MINIMIZE; + + if (!(flags & META_FRAME_ALLOWS_DELETE)) + insensitive |= META_MENU_OP_DELETE; + + if (frames->menu) + gtk_widget_destroy (frames->menu); + + frames->menu = gtk_menu_new (); i = 0; while (i < G_N_ELEMENTS (menuitems)) @@ -219,13 +171,55 @@ meta_window_menu_show (gulong xwindow, } else { - if (menuitems[i].stock_id) + GtkWidget *image; + GdkPixmap *pix; + GdkBitmap *mask; + + image = NULL; + pix = NULL; + mask = NULL; + + switch (menuitems[i].op) { - GtkWidget *image; + case META_MENU_OP_MAXIMIZE: + meta_frames_get_pixmap_for_control (frames, + META_FRAME_CONTROL_MAXIMIZE, + &pix, &mask); + break; - mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label); + case META_MENU_OP_MINIMIZE: + meta_frames_get_pixmap_for_control (frames, + META_FRAME_CONTROL_MINIMIZE, + &pix, &mask); + break; + + case META_MENU_OP_DELETE: + meta_frames_get_pixmap_for_control (frames, + META_FRAME_CONTROL_DELETE, + &pix, &mask); + break; + default: + break; + } + + if (pix) + { + image = gtk_image_new_from_pixmap (pix, mask); + g_object_unref (G_OBJECT (pix)); + g_object_unref (G_OBJECT (mask)); + } + + if (image == NULL && + menuitems[i].stock_id) + { image = gtk_image_new_from_stock (menuitems[i].stock_id, GTK_ICON_SIZE_MENU); + + } + + if (image) + { + mi = gtk_image_menu_item_new_with_mnemonic (menuitems[i].label); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); gtk_widget_show (image); @@ -240,16 +234,19 @@ meta_window_menu_show (gulong xwindow, md = g_new (MenuData, 1); - md->window = window; + md->frames = frames; + md->frame = frame; md->op = menuitems[i].op; - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); + gtk_signal_connect_full (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + NULL, + md, + g_free, FALSE, FALSE); } - gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_menu_shell_append (GTK_MENU_SHELL (frames->menu), mi); gtk_widget_show (mi); @@ -257,13 +254,14 @@ meta_window_menu_show (gulong xwindow, ++i; } - if (ops & META_MESSAGE_MENU_WORKSPACES) + if (ops & META_MENU_OP_WORKSPACES) { - n_workspaces = get_num_desktops (); - current_workspace = get_current_desktop (window); + n_workspaces = meta_core_get_num_workspaces (DefaultScreenOfDisplay (gdk_display)); + current_workspace = meta_core_get_frame_workspace (gdk_display, + frame->xwindow); - meta_ui_warning ("Creating %d workspace menu current %d\n", - n_workspaces, current_workspace); + meta_warning ("Creating %d-workspace menu current %d\n", + n_workspaces, current_workspace); if (n_workspaces > 0) { @@ -275,7 +273,7 @@ meta_window_menu_show (gulong xwindow, char *label; MenuData *md; - if (current_workspace == 0xFFFFFFFF) + if (flags & META_FRAME_STUCK) label = g_strdup_printf (_("Only on workspace _%d\n"), i + 1); else @@ -286,25 +284,29 @@ meta_window_menu_show (gulong xwindow, g_free (label); - if (current_workspace == i || - insensitive & META_MESSAGE_MENU_WORKSPACES) + if (!(flags & META_FRAME_STUCK) && + (current_workspace == i || + insensitive & META_MENU_OP_WORKSPACES)) gtk_widget_set_sensitive (mi, FALSE); md = g_new (MenuData, 1); - md->window = window; - md->op = META_MESSAGE_MENU_WORKSPACES; + md->frames = frames; + md->frame = frame; + md->op = META_MENU_OP_WORKSPACES; g_object_set_data (G_OBJECT (mi), "workspace", GINT_TO_POINTER (i)); - gtk_signal_connect (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - md); + gtk_signal_connect_full (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + NULL, + md, + g_free, FALSE, FALSE); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_menu_shell_append (GTK_MENU_SHELL (frames->menu), mi); gtk_widget_show (mi); @@ -314,16 +316,16 @@ meta_window_menu_show (gulong xwindow, } } else - meta_ui_warning ("not creating workspace menu\n"); + meta_verbose ("not creating workspace menu\n"); + + gtk_signal_connect (GTK_OBJECT (frames->menu), + "selection_done", + GTK_SIGNAL_FUNC (menu_closed), + frames); - gtk_signal_connect (GTK_OBJECT (menu), - "destroy", - GTK_SIGNAL_FUNC (gtk_widget_destroyed), - &menu); - pt = g_new (GdkPoint, 1); - g_object_set_data_full (G_OBJECT (menu), + g_object_set_data_full (G_OBJECT (frames->menu), "destroy-point", pt, g_free); @@ -331,163 +333,82 @@ meta_window_menu_show (gulong xwindow, pt->x = root_x; pt->y = root_y; - gtk_menu_popup (GTK_MENU (menu), + gtk_menu_popup (GTK_MENU (frames->menu), NULL, NULL, popup_position_func, pt, button, timestamp); - if (!GTK_MENU_SHELL (menu)->have_xgrab) - meta_ui_warning ("GtkMenu failed to grab the pointer\n"); -} - -void -meta_window_menu_hide (void) -{ - if (menu) - gtk_widget_destroy (menu); -} - -static void -close_window (GdkWindow *window) -{ - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = GDK_WINDOW_XID (window); - ev.message_type = gdk_atom_intern ("_NET_CLOSE_WINDOW", FALSE); - ev.format = 32; - ev.data.l[0] = 0; - ev.data.l[1] = 0; - - gdk_error_trap_push (); - XSendEvent (gdk_display, - gdk_root_window, False, - SubstructureNotifyMask | SubstructureRedirectMask, - (XEvent*) &ev); - gdk_flush (); - gdk_error_trap_pop (); -} - -static void -wmspec_change_state (gboolean add, - GdkWindow *window, - GdkAtom state1, - GdkAtom state2) -{ - XEvent xev; - gulong op; - - if (add) - op = _NET_WM_STATE_ADD; - else - op = _NET_WM_STATE_REMOVE; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = GDK_WINDOW_XID (window); - xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE); - xev.xclient.format = 32; - xev.xclient.data.l[0] = op; - xev.xclient.data.l[1] = state1; - xev.xclient.data.l[2] = state2; - - XSendEvent (gdk_display, gdk_root_window, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); -} - -static void -wmspec_change_desktop (GdkWindow *window, - gint desktop) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = GDK_WINDOW_XID (window); - xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE); - xev.xclient.format = 32; - xev.xclient.data.l[0] = desktop; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, gdk_root_window, False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); + if (!GTK_MENU_SHELL (frames->menu)->have_xgrab) + meta_warning ("GtkMenu failed to grab the pointer\n"); } static void activate_cb (GtkWidget *menuitem, gpointer data) { MenuData *md; - + + g_return_if_fail (GTK_IS_WIDGET (menuitem)); + md = data; switch (md->op) { - case META_MESSAGE_MENU_DELETE: - close_window (md->window); + case META_MENU_OP_DELETE: + meta_core_delete (gdk_display, + md->frame->xwindow, + gtk_get_current_event_time ()); break; - case META_MESSAGE_MENU_MINIMIZE: - gdk_window_iconify (md->window); + case META_MENU_OP_MINIMIZE: + meta_core_minimize (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_UNMAXIMIZE: - wmspec_change_state (FALSE, md->window, - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE), - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE)); + case META_MENU_OP_UNMAXIMIZE: + meta_core_unmaximize (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_MAXIMIZE: - wmspec_change_state (TRUE, md->window, - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE), - gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE)); + case META_MENU_OP_MAXIMIZE: + meta_core_maximize (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_UNSHADE: - wmspec_change_state (FALSE, md->window, - gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), - 0); + case META_MENU_OP_UNSHADE: + meta_core_unshade (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_SHADE: - wmspec_change_state (TRUE, md->window, - gdk_atom_intern ("_NET_WM_STATE_SHADED", FALSE), - 0); + case META_MENU_OP_SHADE: + meta_core_shade (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_WORKSPACES: + case META_MENU_OP_WORKSPACES: { int workspace; workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "workspace")); - wmspec_change_desktop (md->window, workspace); + meta_core_change_workspace (gdk_display, md->frame->xwindow, + workspace); } break; - case META_MESSAGE_MENU_STICK: - wmspec_change_desktop (md->window, 0xFFFFFFFF); + case META_MENU_OP_STICK: + meta_core_stick (gdk_display, + md->frame->xwindow); break; - case META_MESSAGE_MENU_UNSTICK: - wmspec_change_desktop (md->window, get_active_desktop ()); + case META_MENU_OP_UNSTICK: + meta_core_unstick (gdk_display, + md->frame->xwindow); break; default: - meta_ui_warning (G_STRLOC": Unknown window op\n"); + meta_warning (G_STRLOC": Unknown window op\n"); break; } - - if (menu) - gtk_widget_destroy (menu); - g_object_unref (G_OBJECT (md->window)); - g_free (md); } diff --git a/src/menu.h b/src/menu.h index de08979a5..30a096fc2 100644 --- a/src/menu.h +++ b/src/menu.h @@ -31,7 +31,6 @@ void meta_window_menu_show (MetaFrames *frames, int root_y, int button, guint32 timestamp); -void meta_window_menu_hide (void); diff --git a/src/util.c b/src/util.c index 0da9a82bc..4150a8a36 100644 --- a/src/util.c +++ b/src/util.c @@ -130,6 +130,8 @@ meta_debug_spew (const char *format, ...) if (no_prefix == 0) fputs ("Window manager: ", out); fputs (str, out); + + fflush (out); g_free (str); } @@ -155,6 +157,8 @@ meta_verbose (const char *format, ...) if (no_prefix == 0) fputs ("Window manager: ", out); fputs (str, out); + + fflush (out); g_free (str); } @@ -177,6 +181,8 @@ meta_bug (const char *format, ...) if (no_prefix == 0) fputs ("Bug in window manager: ", out); fputs (str, out); + + fflush (out); g_free (str); @@ -224,6 +230,8 @@ meta_fatal (const char *format, ...) if (no_prefix == 0) fputs ("Window manager: ", out); fputs (str, out); + + fflush (out); g_free (str); diff --git a/src/util.h b/src/util.h index 904a789c5..88927301c 100644 --- a/src/util.h +++ b/src/util.h @@ -49,6 +49,7 @@ void meta_pop_no_msg_prefix (void); /* FIXME */ #include #define _(x) x +#define N_(x) x #endif diff --git a/src/window.c b/src/window.c index f06059106..49541f15f 100644 --- a/src/window.c +++ b/src/window.c @@ -1479,7 +1479,9 @@ process_property_notify (MetaWindow *window, meta_warning ("Broken client changed client leader window or SM client ID\n"); } else if (event->atom == - window->display->atom_net_wm_window_type) + window->display->atom_net_wm_window_type || + /* update_net_wm_type falls back to this */ + event->atom == window->display->atom_win_layer) { update_net_wm_type (window); } @@ -1993,12 +1995,14 @@ update_mwm_hints (MetaWindow *window) result = meta_error_trap_pop (window->display); - if (result != Success) - return result; + if (result != Success || + type == None) + { + meta_verbose ("Window %s has no MWM hints\n", window->desc); + /* may be Success, unused anyhow */ + return result; + } - if (type == None) - return -1; /* whatever */ - /* We support MWM hints deemed non-stupid */ meta_verbose ("Window %s has MWM hints\n", @@ -2006,14 +2010,20 @@ update_mwm_hints (MetaWindow *window) if (hints->flags & MWM_HINTS_DECORATIONS) { - meta_verbose ("Window %s sets MWM decorations to 0x%lx\n", + meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%lx\n", window->desc, hints->decorations); + if (hints->decorations == 0) window->decorated = FALSE; } + else + meta_verbose ("Decorations flag unset\n"); if (hints->flags & MWM_HINTS_FUNCTIONS) { + meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%lx\n", + window->desc, hints->functions); + if ((hints->functions & MWM_FUNC_CLOSE) == 0) { meta_verbose ("Window %s disables close via MWM hints\n", @@ -2033,6 +2043,8 @@ update_mwm_hints (MetaWindow *window) window->has_maximize_func = FALSE; } } + else + meta_verbose ("Functions flag unset\n"); XFree (hints); @@ -2241,6 +2253,52 @@ update_transient_for (MetaWindow *window) return meta_error_trap_pop (window->display); } + +static gboolean +get_cardinal (MetaWindow *window, + Atom atom, + gulong *val) +{ + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + gulong *num; + int err; + + meta_error_trap_push (window->display); + type = None; + XGetWindowProperty (window->display->xdisplay, + window->xwindow, + atom, + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, (guchar **)&num); + err = meta_error_trap_pop (window->display); + if (err != Success) + return FALSE; + + if (type != XA_CARDINAL) + return FALSE; + + *val = *num; + + XFree (num); + + return TRUE; +} + +/* some legacy cruft */ +typedef enum +{ + WIN_LAYER_DESKTOP = 0, + WIN_LAYER_BELOW = 2, + WIN_LAYER_NORMAL = 4, + WIN_LAYER_ONTOP = 6, + WIN_LAYER_DOCK = 8, + WIN_LAYER_ABOVE_DOCK = 10 +} GnomeWinLayer; + static int update_net_wm_type (MetaWindow *window) { @@ -2262,17 +2320,39 @@ update_net_wm_type (MetaWindow *window) &bytes_after, (guchar **)&atoms); result = meta_error_trap_pop (window->display); - if (result != Success) + if (result != Success || + type != XA_ATOM) { + /* Fall back to WIN_LAYER */ + gulong layer = WIN_LAYER_NORMAL; + + if (get_cardinal (window, window->display->atom_win_layer, + &layer)) + { + meta_verbose ("%s falling back to _WIN_LAYER hint, layer %ld\n", + window->desc, layer); + switch (layer) + { + case WIN_LAYER_DESKTOP: + window->type_atom = + window->display->atom_net_wm_window_type_desktop; + break; + case WIN_LAYER_NORMAL: + window->type_atom = + window->display->atom_net_wm_window_type_normal; + break; + case WIN_LAYER_DOCK: + window->type_atom = + window->display->atom_net_wm_window_type_dock; + break; + default: + break; + } + } + recalc_window_type (window); return result; } - - if (type != XA_ATOM) - { - recalc_window_type (window); - return -1; /* whatever */ - } i = 0; while (i < n_atoms) @@ -2316,40 +2396,6 @@ update_net_wm_type (MetaWindow *window) return Success; } -static gboolean -get_cardinal (MetaWindow *window, - Atom atom, - gulong *val) -{ - Atom type; - gint format; - gulong nitems; - gulong bytes_after; - gulong *num; - int err; - - meta_error_trap_push (window->display); - type = None; - XGetWindowProperty (window->display->xdisplay, - window->xwindow, - atom, - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, (guchar **)&num); - err = meta_error_trap_pop (window->display); - if (err != Success) - return FALSE; - - if (type != XA_CARDINAL) - return FALSE; - - *val = *num; - - XFree (num); - - return TRUE; -} - static int update_initial_workspace (MetaWindow *window) { diff --git a/src/window.h b/src/window.h index f8149feba..03dacb0e8 100644 --- a/src/window.h +++ b/src/window.h @@ -220,4 +220,6 @@ gboolean meta_window_client_message (MetaWindow *window, XEvent *event); int meta_window_set_current_workspace_hint (MetaWindow *window); + +unsigned long meta_window_get_net_wm_desktop (MetaWindow *window); #endif