X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=930f3ee4d174571bd5e2576383133dd66a6b6a14;hb=425dc318088b4c675cc0d7e6d75c6ff552cee448;hp=a465f566326d58d29256d1addaef02eee7eef64b;hpb=b2b8ad92bfbc60392737fe9945e719b238d34933;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index a465f566..930f3ee4 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -126,7 +126,7 @@ void client_set_list() windows = NULL; PROP_SETA32(RootWindow(ob_display, ob_screen), - net_client_list, window, (guint32*)windows, size); + net_client_list, window, (gulong*)windows, size); if (windows) g_free(windows); @@ -344,20 +344,31 @@ void client_manage(Window window) place_client(self, &x, &y); - /* make sure the window is visible */ + /* make sure the window is visible. */ client_find_onscreen(self, &x, &y, self->frame->area.width, self->frame->area.height, /* non-normal clients has less rules, and - windows that are being restored from a session - do also. we can assume you want it back where - you saved it */ - client_normal(self) && !self->session); - - if (x != ox || y != oy) + windows that are being restored from a + session do also. we can assume you want + it back where you saved it. Clients saying + they placed themselves are subjected to + harder rules, ones that are placed by + place.c or by the user are allowed partially + off-screen and on xinerama divides (ie, + it is up to the placement routines to avoid + the xinerama divides) */ + ((self->positioned & PPosition) && + !(self->positioned & USPosition)) && + client_normal(self) && + !self->session); + if (x != ox || y != oy) client_move(self, x, y); } + keyboard_grab_for_client(self, TRUE); + mouse_grab_for_client(self, TRUE); + client_showhide(self); /* use client_focus instead of client_activate cuz client_activate does @@ -392,9 +403,6 @@ void client_manage(Window window) /* update the list hints */ client_set_list(); - keyboard_grab_for_client(self, TRUE); - mouse_grab_for_client(self, TRUE); - ob_debug("Managed window 0x%lx (%s)\n", window, self->class); } @@ -460,8 +468,6 @@ void client_unmanage(ObClient *self) /* tell our parent(s) that we're gone */ if (self->transient_for == OB_TRAN_GROUP) { /* transient of group */ - GSList *it; - for (it = self->group->members; it; it = g_slist_next(it)) if (it->data != self) ((ObClient*)it->data)->transients = @@ -546,7 +552,7 @@ static void client_restore_session_state(ObClient *self) self->session = it->data; RECT_SET_POINT(self->area, self->session->x, self->session->y); - self->positioned = TRUE; + self->positioned = PPosition; if (self->session->w > 0) self->area.width = self->session->w; if (self->session->h > 0) @@ -613,9 +619,10 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, would be */ /* XXX watch for xinerama dead areas */ - - a = screen_area(self->desktop); + /* This makes sure windows aren't entirely outside of the screen so you + * can't see them at all */ if (client_normal(self)) { + a = screen_area(self->desktop); if (!self->strut.right && *x >= a->x + a->width - 1) *x = a->x + a->width - self->frame->area.width; if (!self->strut.bottom && *y >= a->y + a->height - 1) @@ -626,10 +633,17 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, *y = a->y; } + /* This here doesn't let windows even a pixel outside the screen, + * when called from client_manage, programs placing themselves are + * forced completely onscreen, while things like + * xterm -geometry resolution-width/2 will work fine. Trying to + * place it completely offscreen will be handled in the above code. + * Sorry for this confused comment, i am tired. */ if (rude) { - /* this is my MOZILLA BITCHSLAP. oh ya it fucking feels good. - Java can suck it too. */ - + /* avoid the xinerama monitor divide while we're at it, + * remember to fix the placement stuff to avoid it also and + * then remove this XXX */ + a = screen_physical_area_monitor(client_monitor(self)); /* dont let windows map/move into the strut unless they are bigger than the available area */ if (w <= a->width) { @@ -1113,7 +1127,7 @@ void client_update_normal_hints(ObClient *self) /* normal windows can't request placement! har har if (!client_normal(self)) */ - self->positioned = !!(size.flags & (PPosition|USPosition)); + self->positioned = (size.flags & (PPosition|USPosition)); if (size.flags & PWinGravity) { self->gravity = size.win_gravity; @@ -1257,8 +1271,12 @@ void client_setup_decor_and_functions(ObClient *self) /* finally, the user can have requested no decorations, which overrides everything (but doesnt give it a border if it doesnt have one) */ - if (self->undecorated) - self->decorations = 0; //&= OB_FRAME_DECOR_BORDER; + if (self->undecorated) { + if (config_theme_keepborder) + self->decorations &= OB_FRAME_DECOR_BORDER; + else + self->decorations = 0; + } /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) @@ -1282,7 +1300,7 @@ void client_setup_decor_and_functions(ObClient *self) static void client_change_allowed_actions(ObClient *self) { - guint32 actions[9]; + gulong actions[9]; gint num = 0; /* desktop windows are kept on all desktops */ @@ -1442,14 +1460,17 @@ void client_update_title(ObClient *self) old_title = self->title; /* try netwm */ - if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) + if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) { /* try old x stuff */ - if (!PROP_GETS(self->window, wm_name, locale, &data)) + if (!PROP_GETS(self->window, wm_name, locale, &data)) { // http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html - if (self->transient) - data = '\0'; - else + if (self->transient) { + data = g_strdup(""); + goto no_number; + } else data = g_strdup("Unnamed Window"); + } + } /* did the title change? then reset the title_count */ if (old_title && 0 != strncmp(old_title, data, strlen(data))) @@ -1479,7 +1500,7 @@ void client_update_title(ObClient *self) } PROP_SETS(self->window, net_wm_visible_name, data); - +no_number: self->title = data; if (self->frame) @@ -1694,8 +1715,8 @@ void client_update_icons(ObClient *self) static void client_change_state(ObClient *self) { - guint32 state[2]; - guint32 netstate[11]; + gulong state[2]; + gulong netstate[11]; guint num; state[0] = self->wmstate; @@ -1783,9 +1804,8 @@ static ObStackingLayer calc_layer(ObClient *self) else if (self->type == OB_CLIENT_TYPE_DESKTOP) l = OB_STACKING_LAYER_DESKTOP; else if (self->type == OB_CLIENT_TYPE_DOCK) { - if (self->above) l = OB_STACKING_LAYER_DOCK_ABOVE; - else if (self->below) l = OB_STACKING_LAYER_DOCK_BELOW; - else l = OB_STACKING_LAYER_DOCK_NORMAL; + if (self->below) l = OB_STACKING_LAYER_NORMAL; + else l = OB_STACKING_LAYER_ABOVE; } else if (self->above) l = OB_STACKING_LAYER_ABOVE; else if (self->below) l = OB_STACKING_LAYER_BELOW; @@ -2522,6 +2542,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) gboolean max_horz = self->max_horz; gboolean max_vert = self->max_vert; gboolean modal = self->modal; + gboolean iconic = self->iconic; gint i; if (!(action == prop_atoms.net_wm_state_add || @@ -2557,6 +2578,10 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) action = self->skip_pager ? prop_atoms.net_wm_state_remove : prop_atoms.net_wm_state_add; + else if (state == prop_atoms.net_wm_state_hidden) + action = self->iconic ? + prop_atoms.net_wm_state_remove : + prop_atoms.net_wm_state_add; else if (state == prop_atoms.net_wm_state_fullscreen) action = fullscreen ? prop_atoms.net_wm_state_remove : @@ -2585,6 +2610,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) self->skip_taskbar = TRUE; } else if (state == prop_atoms.net_wm_state_skip_pager) { self->skip_pager = TRUE; + } else if (state == prop_atoms.net_wm_state_hidden) { + iconic = TRUE; } else if (state == prop_atoms.net_wm_state_fullscreen) { fullscreen = TRUE; } else if (state == prop_atoms.net_wm_state_above) { @@ -2610,6 +2637,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) self->skip_taskbar = FALSE; } else if (state == prop_atoms.net_wm_state_skip_pager) { self->skip_pager = FALSE; + } else if (state == prop_atoms.net_wm_state_hidden) { + iconic = FALSE; } else if (state == prop_atoms.net_wm_state_fullscreen) { fullscreen = FALSE; } else if (state == prop_atoms.net_wm_state_above) { @@ -2652,6 +2681,9 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) transients needs to change */ client_raise(self); } + if (iconic != self->iconic) + client_iconify(self, iconic, FALSE); + client_calc_layer(self); client_change_state(self); /* change the hint to reflect these changes */ } @@ -2765,6 +2797,9 @@ void client_unfocus(ObClient *self) void client_activate(ObClient *self, gboolean here) { + /* This check is for the client_list_menu trying to activate + * a closed client. */ + if (!g_list_find(client_list, self)) return; if (client_normal(self) && screen_showing_desktop) screen_show_desktop(FALSE); if (self->iconic) @@ -2892,7 +2927,10 @@ ObClient *client_find_directional(ObClient *c, ObDirection dir) continue; if (!client_normal(cur)) continue; - if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + /* using c->desktop instead of screen_desktop doesn't work if the + * current window was omnipresent, hope this doesn't have any other + * side effects */ + if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) continue; if(cur->iconic) continue; @@ -2982,10 +3020,20 @@ void client_set_undecorated(ObClient *self, gboolean undecorated) if (self->undecorated != undecorated) { self->undecorated = undecorated; client_setup_decor_and_functions(self); + /* Make sure the client knows it might have moved. Maybe there is a + * better way of doing this so only one client_configure is sent, but + * since 125 of these are sent per second when moving the window (with + * user = FALSE) i doubt it matters much. + */ + client_configure(self, OB_CORNER_TOPLEFT, self->area.x, self->area.y, + self->area.width, self->area.height, TRUE, TRUE); client_change_state(self); /* reflect this in the state hints */ } } +/* Determines which physical monitor a client is on by calculating the + area of the part of the client on each monitor. The number of the + monitor containing the greatest area of the client is returned.*/ guint client_monitor(ObClient *self) { guint i; @@ -3112,15 +3160,16 @@ void client_update_sm_client_id(ObClient *self) */ gint client_directional_edge_search(ObClient *c, ObDirection dir) { - gint dest; + gint dest, monitor_dest; gint my_edge_start, my_edge_end, my_offset; GList *it; - Rect *a; + Rect *a, *monitor; if(!client_list) return -1; a = screen_area(c->desktop); + monitor = screen_area_monitor(c->desktop, client_monitor(c)); switch(dir) { case OB_DIRECTION_NORTH: @@ -3130,8 +3179,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) /* default: top of screen */ dest = a->y; + monitor_dest = monitor->y; + /* if the monitor edge comes before the screen edge, */ + /* use that as the destination instead. (For xinerama) */ + if (monitor_dest != dest && my_offset > monitor_dest) + dest = monitor_dest; - for(it = client_list; it; it = g_list_next(it)) { + for(it = client_list; it && my_offset != dest; it = g_list_next(it)) { gint his_edge_start, his_edge_end, his_offset; ObClient *cur = it->data; @@ -3139,10 +3193,12 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) continue; if(!client_normal(cur)) continue; - if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) continue; if(cur->iconic) continue; + if(cur->layer < c->layer && !config_resist_layers_below) + continue; his_edge_start = cur->frame->area.x; his_edge_end = cur->frame->area.x + cur->frame->area.width; @@ -3171,8 +3227,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) /* default: bottom of screen */ dest = a->y + a->height; + monitor_dest = monitor->y + monitor->height; + /* if the monitor edge comes before the screen edge, */ + /* use that as the destination instead. (For xinerama) */ + if (monitor_dest != dest && my_offset < monitor_dest) + dest = monitor_dest; - for(it = client_list; it; it = g_list_next(it)) { + for(it = client_list; it && my_offset != dest; it = g_list_next(it)) { gint his_edge_start, his_edge_end, his_offset; ObClient *cur = it->data; @@ -3180,10 +3241,12 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) continue; if(!client_normal(cur)) continue; - if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) continue; if(cur->iconic) continue; + if(cur->layer < c->layer && !config_resist_layers_below) + continue; his_edge_start = cur->frame->area.x; his_edge_end = cur->frame->area.x + cur->frame->area.width; @@ -3213,8 +3276,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) /* default: leftmost egde of screen */ dest = a->x; + monitor_dest = monitor->x; + /* if the monitor edge comes before the screen edge, */ + /* use that as the destination instead. (For xinerama) */ + if (monitor_dest != dest && my_offset > monitor_dest) + dest = monitor_dest; - for(it = client_list; it; it = g_list_next(it)) { + for(it = client_list; it && my_offset != dest; it = g_list_next(it)) { gint his_edge_start, his_edge_end, his_offset; ObClient *cur = it->data; @@ -3222,10 +3290,12 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) continue; if(!client_normal(cur)) continue; - if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) continue; if(cur->iconic) continue; + if(cur->layer < c->layer && !config_resist_layers_below) + continue; his_edge_start = cur->frame->area.y; his_edge_end = cur->frame->area.y + cur->frame->area.height; @@ -3255,8 +3325,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) /* default: rightmost edge of screen */ dest = a->x + a->width; + monitor_dest = monitor->x + monitor->width; + /* if the monitor edge comes before the screen edge, */ + /* use that as the destination instead. (For xinerama) */ + if (monitor_dest != dest && my_offset < monitor_dest) + dest = monitor_dest; - for(it = client_list; it; it = g_list_next(it)) { + for(it = client_list; it && my_offset != dest; it = g_list_next(it)) { gint his_edge_start, his_edge_end, his_offset; ObClient *cur = it->data; @@ -3264,10 +3339,12 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) continue; if(!client_normal(cur)) continue; - if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) continue; if(cur->iconic) continue; + if(cur->layer < c->layer && !config_resist_layers_below) + continue; his_edge_start = cur->frame->area.y; his_edge_end = cur->frame->area.y + cur->frame->area.height; @@ -3296,6 +3373,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir) /* not implemented */ default: g_assert_not_reached(); + dest = 0; /* suppress warning */ } return dest; }