X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=cfcc7da22c4241e28d31835717509dd907fba3de;hb=8af51d8a1be9c3cb9d89d1d8378de72f42599760;hp=f5ca0005af35840dc385515a21b67672190f5556;hpb=349990a3b5c77fdeb313c75c8cd2ca31f1d5a76c;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index f5ca0005..cfcc7da2 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); @@ -204,6 +204,26 @@ void client_manage_all() XFree(children); } +/* This should possibly do something more interesting than just match + * against WM_CLASS literally. */ +static ObAppSettings *get_settings(ObClient *client) +{ + GSList *a = config_per_app_settings; + + while (a) { + ObAppSettings *app = (ObAppSettings *) a->data; + + if (!strcmp(app->name, client->name)) { + ob_debug("Window matching: %s\n", app->name); + if (!app->role || !strcmp(app->role, client->role)) + return app; + } + + a = a->next; + } + return NULL; +} + void client_manage(Window window) { ObClient *self; @@ -212,6 +232,7 @@ void client_manage(Window window) XSetWindowAttributes attrib_set; XWMHints *wmhint; gboolean activate = FALSE; + ObAppSettings *settings; grab_server(TRUE); @@ -292,12 +313,29 @@ void client_manage(Window window) client_apply_startup_state(self); + /* get and set application level settings */ + settings = get_settings(self); + + if (settings) { + if (settings->shade && !settings->decor) + settings->decor = TRUE; + + client_shade(self, settings->shade); + client_set_undecorated(self, !settings->decor); + + if (settings->desktop != -1) + client_set_desktop(self, settings->desktop, FALSE); + + client_set_layer(self, settings->layer); + } + stacking_add(CLIENT_AS_WINDOW(self)); client_restore_session_stacking(self); /* focus the new window? */ if (ob_state() != OB_STATE_STARTING && - (config_focus_new || client_search_focus_parent(self)) && + (config_focus_new || client_search_focus_parent(self)) || + (settings && settings->focus) && /* note the check against Type_Normal/Dialog, not client_normal(self), which would also include other types. in this case we want more strict rules for focus */ @@ -342,22 +380,33 @@ void client_manage(Window window) gint x = self->area.x, ox = x; gint y = self->area.y, oy = y; - place_client(self, &x, &y); + place_client(self, &x, &y, settings); - /* 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 +441,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); } @@ -544,7 +590,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) @@ -611,9 +657,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) @@ -624,10 +671,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) { @@ -1111,7 +1165,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; @@ -1212,7 +1266,7 @@ void client_setup_decor_and_functions(ObClient *self) (self->mwmhints.decorations & OB_MWM_DECOR_TITLE))) /* if the mwm hints request no handle or title, then all decorations are disabled */ - self->decorations = 0; + self->decorations = config_theme_keepborder ? OB_FRAME_DECOR_BORDER : 0; } } @@ -1284,7 +1338,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 */ @@ -1699,8 +1753,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; @@ -1788,9 +1842,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; @@ -2782,6 +2835,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) @@ -3002,10 +3058,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; @@ -3132,15 +3198,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: @@ -3150,8 +3217,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; @@ -3193,8 +3265,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; @@ -3237,8 +3314,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; @@ -3281,8 +3363,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;