X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=e58cc753733078743560748dcc0c7399e545aa73;hb=97792a403a52c12c2601a7b2caebdea197f0b5f0;hp=1ead992c2d22ed9fedfa6d7b854c12136a71c02b;hpb=cbaafd2ff9194570686cc242910f81e104ee8c42;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 1ead992c..e58cc753 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -88,7 +88,8 @@ static void client_update_transient_tree(ObClient *self, gboolean oldgtran, gboolean newgtran, ObClient* oldparent, ObClient *newparent); -static void client_present(ObClient *self, gboolean here, gboolean raise); +static void client_present(ObClient *self, gboolean here, gboolean raise, + gboolean unshade); static GSList *client_search_all_top_parents_internal(ObClient *self, gboolean bylayer, ObStackingLayer layer); @@ -394,7 +395,7 @@ void client_manage(Window window) */ if (ob_state() == OB_STATE_RUNNING && (transient || - (!(self->sized & USSize) && + (!(self->sized & USSize || self->positioned & USPosition) && client_normal(self) && !self->session))) { @@ -403,8 +404,7 @@ void client_manage(Window window) RECT_SET(placer, placex, placey, placew, placeh); frame_rect_to_frame(self->frame, &placer); - Rect *a = screen_area_monitor(self->desktop, client_monitor(self), - &placer); + Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer); /* shrink by the frame's area */ a->width -= self->frame->size.left + self->frame->size.right; @@ -545,7 +545,7 @@ void client_manage(Window window) if (activate) { gboolean stacked = client_restore_session_stacking(self); - client_present(self, FALSE, !stacked); + client_present(self, FALSE, !stacked, TRUE); } /* add to client list/map */ @@ -923,50 +923,24 @@ void client_move_onscreen(ObClient *self, gboolean rude) gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, gboolean rude) { - Rect *mon_a, *all_a; gint ox = *x, oy = *y; gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude; gint fw, fh; Rect desired; + guint i; RECT_SET(desired, *x, *y, w, h); frame_rect_to_frame(self->frame, &desired); - all_a = screen_area(self->desktop, &desired); - mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired), - &desired); - /* get where the frame would be */ - frame_client_gravity(self->frame, x, y, w, h); + frame_client_gravity(self->frame, x, y); /* get the requested size of the window with decorations */ fw = self->frame->size.left + w + self->frame->size.right; fh = self->frame->size.top + h + self->frame->size.bottom; - /* This makes sure windows aren't entirely outside of the screen so you - can't see them at all. - It makes sure 10% of the window is on the screen at least. At don't let - it move itself off the top of the screen, which would hide the titlebar - on you. (The user can still do this if they want too, it's only limiting - the application. - - XXX watch for xinerama dead areas... - */ - if (client_normal(self)) { - if (!self->strut.right && *x + fw/10 >= all_a->x + all_a->width - 1) - *x = all_a->x + all_a->width - fw/10; - if (!self->strut.bottom && *y + fh/10 >= all_a->y + all_a->height - 1) - *y = all_a->y + all_a->height - fh/10; - if (!self->strut.left && *x + fw*9/10 - 1 < all_a->x) - *x = all_a->x - fw*9/10; - if (!self->strut.top && *y + fh*9/10 - 1 < all_a->y) - *y = all_a->y - fw*9/10; - } - - /* If rudeness wasn't requested, then figure out of the client is currently - entirely on the screen. If it is, and the position isn't changing by - request, and it is enlarging, then be rude even though it wasn't - requested */ + /* If rudeness wasn't requested, then still be rude in a given direction + if the client is not moving, only resizing in that direction */ if (!rude) { Point oldtl, oldtr, oldbl, oldbr; Point newtl, newtr, newbl, newbr; @@ -1003,25 +977,51 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, rudeb = TRUE; } - /* This here doesn't let windows even a pixel outside the struts/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 (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x; - if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width) - *x = mon_a->x + MAX(0, mon_a->width - fw); + for (i = 0; i < screen_num_monitors; ++i) { + Rect *a; + + if (!screen_physical_area_monitor_contains(i, &desired)) + continue; - if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y; - if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height) - *y = mon_a->y + MAX(0, mon_a->height - fh); + a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &desired); - /* get where the client should be */ - frame_frame_gravity(self->frame, x, y, w, h); + /* This makes sure windows aren't entirely outside of the screen so you + can't see them at all. + It makes sure 10% of the window is on the screen at least. At don't + let it move itself off the top of the screen, which would hide the + titlebar on you. (The user can still do this if they want too, it's + only limiting the application. + */ + if (client_normal(self)) { + if (!self->strut.right && *x + fw/10 >= a->x + a->width - 1) + *x = a->x + a->width - fw/10; + if (!self->strut.bottom && *y + fh/10 >= a->y + a->height - 1) + *y = a->y + a->height - fh/10; + if (!self->strut.left && *x + fw*9/10 - 1 < a->x) + *x = a->x - fw*9/10; + if (!self->strut.top && *y + fh*9/10 - 1 < a->y) + *y = a->y - fw*9/10; + } - g_free(all_a); - g_free(mon_a); + /* This here doesn't let windows even a pixel outside the + struts/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 (rudel && !self->strut.left && *x < a->x) *x = a->x; + if (ruder && !self->strut.right && *x + fw > a->x + a->width) + *x = a->x + MAX(0, a->width - fw); + + if (rudet && !self->strut.top && *y < a->y) *y = a->y; + if (rudeb && !self->strut.bottom && *y + fh > a->y + a->height) + *y = a->y + MAX(0, a->height - fh); + + g_free(a); + } + + /* get where the client should be */ + frame_frame_gravity(self->frame, x, y); return ox != *x || oy != *y; } @@ -1750,7 +1750,8 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) client_change_allowed_actions(self); if (reconfig) - client_reconfigure(self); + /* force reconfigure to make sure decorations are updated */ + client_reconfigure(self, TRUE); } static void client_change_allowed_actions(ObClient *self) @@ -1808,13 +1809,6 @@ static void client_change_allowed_actions(ObClient *self) } } -void client_reconfigure(ObClient *self) -{ - client_configure(self, self->area.x, self->area.y, - self->area.width, self->area.height, - FALSE, TRUE); -} - void client_update_wmhints(ObClient *self) { XWMHints *hints; @@ -1985,7 +1979,7 @@ void client_update_strut(ObClient *self) got = TRUE; /* use the screen's width/height */ - a = screen_physical_area(); + a = screen_physical_area_all_monitors(); STRUT_PARTIAL_SET(strut, data[0], data[2], data[1], data[3], @@ -2091,8 +2085,11 @@ void client_update_icons(ObClient *self) /* set the default icon onto the window in theory, this could be a race, but if a window doesn't set an icon or removes it entirely, it's not very likely it is going to set one - right away afterwards */ - if (self->nicons == 0) { + right away afterwards + + if it has parents, then one of them will have an icon already + */ + if (self->nicons == 0 && !self->parents) { RrPixel32 *icon = ob_rr_theme->def_win_icon; gulong *data; @@ -2616,11 +2613,18 @@ static void client_apply_startup_state(ObClient *self, else if (max_horz) client_maximize(self, TRUE, 1); - /* if the window hasn't been configured yet, then do so now */ - if (!fullscreen && !max_vert && !max_horz) { - self->area = oldarea; - client_configure(self, x, y, w, h, FALSE, TRUE); - } + /* if the window hasn't been configured yet, then do so now, in fact the + x,y,w,h may _not_ be the same as the area rect, which can end up + meaning that the client isn't properly moved/resized by the fullscreen + function + pho can cause this because it maps at size of the screen but not 0,0 + so openbox moves it on screen to 0,0 (thus x,y=0,0 and area.x,y don't). + then fullscreen'ing makes it go to 0,0 which it thinks it already is at + cuz thats where the pre-fullscreen will be. however the actual area is + not, so this needs to be called even if we have fullscreened/maxed + */ + self->area = oldarea; + client_configure(self, x, y, w, h, FALSE, TRUE, FALSE); /* set the desktop hint, to make sure that it always exists */ PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); @@ -2705,7 +2709,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, frame_adjust_area(self->frame, FALSE, TRUE, TRUE); /* gets the frame's position */ - frame_client_gravity(self->frame, x, y, *w, *h); + frame_client_gravity(self->frame, x, y); /* these positions are frame positions, not client positions */ @@ -2730,11 +2734,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, Rect *a; guint i; - i = screen_find_monitor(&desired); /* use all possible struts when maximizing to the full screen */ - a = screen_area_monitor(self->desktop, i, - (self->max_horz && self->max_vert ? - NULL : &desired)); + i = screen_find_monitor(&desired); + a = screen_area(self->desktop, i, + (self->max_horz && self->max_vert ? NULL : &desired)); /* set the size and position if maximized */ if (self->max_horz) { @@ -2753,7 +2756,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, } /* gets the client's position */ - frame_frame_gravity(self->frame, x, y, *w, *h); + frame_frame_gravity(self->frame, x, y); /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { @@ -2863,11 +2866,11 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, void client_configure(ObClient *self, gint x, gint y, gint w, gint h, - gboolean user, gboolean final) + gboolean user, gboolean final, gboolean force_reply) { gint oldw, oldh; gboolean send_resize_client; - gboolean moved = FALSE, resized = FALSE; + gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE; gboolean fmoved, fresized; guint fdecor = self->frame->decorations; gboolean fhorz = self->frame->max_horz; @@ -2916,34 +2919,49 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, } /* adjust the frame */ - if (fmoved || fresized) + if (fmoved || fresized) { + gulong ignore_start; + if (!user) + ignore_start = event_start_ignore_all_enters(); + frame_adjust_area(self->frame, fmoved, fresized, FALSE); + if (!user) + event_end_ignore_all_enters(ignore_start); + } + + if (!user || final) { + gint oldrx = self->root_pos.x; + gint oldry = self->root_pos.y; + /* we have reset the client to 0 border width, so don't include + it in these coords */ + POINT_SET(self->root_pos, + self->frame->area.x + self->frame->size.left - + self->border_width, + self->frame->area.y + self->frame->size.top - + self->border_width); + if (self->root_pos.x != oldrx || self->root_pos.y != oldry) + rootmoved = TRUE; + } + /* This is kinda tricky and should not be changed.. let me explain! When user = FALSE, then the request is coming from the application itself, and we are more strict about when to send a synthetic ConfigureNotify. We strictly follow the rules of the ICCCM sec 4.1.5 - in this case. + in this case (if force_reply is true) When user = TRUE, then the request is coming from "us", like when we - maximize a window or sometihng. In this case we are more lenient. We + maximize a window or something. In this case we are more lenient. We used to follow the same rules as above, but _Java_ Swing can't handle this. So just to appease Swing, when user = TRUE, we always send a synthetic ConfigureNotify to give the window its root coordinates. */ - if ((!user && !resized) || (user && final)) + if ((!user && !resized && (rootmoved || force_reply)) || + (user && final && rootmoved)) { XEvent event; - /* we have reset the client to 0 border width, so don't include - it in these coords */ - POINT_SET(self->root_pos, - self->frame->area.x + self->frame->size.left - - self->border_width, - self->frame->area.y + self->frame->size.top - - self->border_width); - event.type = ConfigureNotify; event.xconfigure.display = ob_display; event.xconfigure.event = self->window; @@ -3018,6 +3036,9 @@ void client_fullscreen(ObClient *self, gboolean fs) RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0); } + ob_debug("Window %s going fullscreen (%d)\n", + self->title, self->fullscreen); + client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); @@ -3061,7 +3082,7 @@ static void client_iconify_recursive(ObClient *self, if (curdesk && self->desktop != screen_desktop && self->desktop != DESKTOP_ALL) - client_set_desktop(self, screen_desktop, FALSE); + client_set_desktop(self, screen_desktop, FALSE, FALSE); /* this puts it after the current focused window */ focus_order_remove(self); @@ -3176,7 +3197,7 @@ void client_shade(ObClient *self, gboolean shade) client_change_state(self); client_change_wm_state(self); /* the window is being hidden/shown */ /* resize the frame to just the titlebar */ - frame_adjust_area(self->frame, FALSE, FALSE, FALSE); + frame_adjust_area(self->frame, FALSE, TRUE, FALSE); } void client_close(ObClient *self) @@ -3234,7 +3255,8 @@ void client_hilite(ObClient *self, gboolean hilite) void client_set_desktop_recursive(ObClient *self, guint target, - gboolean donthide) + gboolean donthide, + gboolean dontraise) { guint old; GSList *it; @@ -3252,28 +3274,32 @@ void client_set_desktop_recursive(ObClient *self, frame_adjust_state(self->frame); /* 'move' the window to the new desktop */ if (!donthide) - client_showhide(self); + client_hide(self); + client_show(self); /* raise if it was not already on the desktop */ - if (old != DESKTOP_ALL) + if (old != DESKTOP_ALL && !dontraise) stacking_raise(CLIENT_AS_WINDOW(self)); - /* the new desktop's geometry may be different, so we may need to - resize, for example if we are maximized */ - client_reconfigure(self); if (STRUT_EXISTS(self->strut)) screen_update_areas(); + else + /* the new desktop's geometry may be different, so we may need to + resize, for example if we are maximized */ + client_reconfigure(self, FALSE); } /* move all transients */ for (it = self->transients; it; it = g_slist_next(it)) if (it->data != self) if (client_is_direct_child(self, it->data)) - client_set_desktop_recursive(it->data, target, donthide); + client_set_desktop_recursive(it->data, target, + donthide, dontraise); } -void client_set_desktop(ObClient *self, guint target, gboolean donthide) +void client_set_desktop(ObClient *self, guint target, + gboolean donthide, gboolean dontraise) { self = client_search_top_direct_parent(self); - client_set_desktop_recursive(self, target, donthide); + client_set_desktop_recursive(self, target, donthide, dontraise); } gboolean client_is_direct_child(ObClient *parent, ObClient *child) @@ -3546,6 +3572,10 @@ gboolean client_focus(ObClient *self) "Focusing client \"%s\" (0x%x) at time %u\n", self->title, self->window, event_curtime); + /* if using focus_delay, stop the timer now so that focus doesn't + go moving on us */ + event_halt_focus_delay(); + /* if there is a grab going on, then we need to cancel it. if we move focus during the grab, applications will get NotifyWhileGrabbed events and ignore them ! @@ -3586,17 +3616,9 @@ gboolean client_focus(ObClient *self) return !xerror_occured; } -/*! Present the client to the user. - @param raise If the client should be raised or not. You should only set - raise to false if you don't care if the window is completely - hidden. -*/ -static void client_present(ObClient *self, gboolean here, gboolean raise) +static void client_present(ObClient *self, gboolean here, gboolean raise, + gboolean unshade) { - /* if using focus_delay, stop the timer now so that focus doesn't - go moving on us */ - event_halt_focus_delay(); - if (client_normal(self) && screen_showing_desktop) screen_show_desktop(FALSE, self); if (self->iconic) @@ -3605,14 +3627,14 @@ static void client_present(ObClient *self, gboolean here, gboolean raise) self->desktop != screen_desktop) { if (here) - client_set_desktop(self, screen_desktop, FALSE); + client_set_desktop(self, screen_desktop, FALSE, TRUE); else screen_set_desktop(self->desktop, FALSE); } else if (!self->frame->visible) /* if its not visible for other reasons, then don't mess with it */ return; - if (self->shaded) + if (self->shaded && unshade) client_shade(self, FALSE); if (raise) stacking_raise(CLIENT_AS_WINDOW(self)); @@ -3620,7 +3642,8 @@ static void client_present(ObClient *self, gboolean here, gboolean raise) client_focus(self); } -void client_activate(ObClient *self, gboolean here, gboolean user) +void client_activate(ObClient *self, gboolean here, gboolean raise, + gboolean unshade, gboolean user) { guint32 last_time = focus_client ? focus_client->user_time : CurrentTime; gboolean allow = FALSE; @@ -3646,7 +3669,7 @@ void client_activate(ObClient *self, gboolean here, gboolean user) (user ? "user" : "application"), allow); if (allow) - client_present(self, here, TRUE); + client_present(self, here, raise, unshade); else /* don't focus it but tell the user it wants attention */ client_hilite(self, TRUE); @@ -3672,7 +3695,7 @@ static void client_bring_windows_recursive(ObClient *self, if (iconic && self->iconic) client_iconify(self, FALSE, TRUE, FALSE); else - client_set_desktop(self, desktop, FALSE); + client_set_desktop(self, desktop, FALSE, FALSE); } } @@ -3876,14 +3899,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) gint dest, monitor_dest; gint my_edge_start, my_edge_end, my_offset; GList *it; - Rect *a, *monitor; + Rect *a, *mon; if(!client_list) return -1; - a = screen_area(c->desktop, &c->frame->area); - monitor = screen_area_monitor(c->desktop, client_monitor(c), - &c->frame->area); + a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area); + mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area); switch(dir) { case OB_DIRECTION_NORTH: @@ -3893,7 +3915,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: top of screen */ dest = a->y + (hang ? c->frame->area.height : 0); - monitor_dest = monitor->y + (hang ? c->frame->area.height : 0); + monitor_dest = mon->y + (hang ? c->frame->area.height : 0); /* 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) @@ -3926,7 +3948,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: bottom of screen */ dest = a->y + a->height - (hang ? c->frame->area.height : 0); - monitor_dest = monitor->y + monitor->height - + monitor_dest = mon->y + mon->height - (hang ? c->frame->area.height : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ @@ -3961,7 +3983,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: leftmost egde of screen */ dest = a->x + (hang ? c->frame->area.width : 0); - monitor_dest = monitor->x + (hang ? c->frame->area.width : 0); + monitor_dest = mon->x + (hang ? c->frame->area.width : 0); /* 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) @@ -3994,7 +4016,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: rightmost edge of screen */ dest = a->x + a->width - (hang ? c->frame->area.width : 0); - monitor_dest = monitor->x + monitor->width - + monitor_dest = mon->x + mon->width - (hang ? c->frame->area.width : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ @@ -4032,7 +4054,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) } g_free(a); - g_free(monitor); + g_free(mon); return dest; } @@ -4069,3 +4091,30 @@ gboolean client_has_group_siblings(ObClient *self) { return self->group && self->group->members->next; } + +ObClientIcon *client_thumbnail(ObClient *self, gint wantw, gint wanth) +{ + ObClientIcon *ret; + RrPixel32 *data; + gint w, h; + + if (!self->frame->pixmap) return NULL; + if (!RrPixmapToRGBA(ob_rr_inst, self->frame->pixmap, None, &w, &h, &data)) + return NULL; + + /* resize the thumbnail (within aspect ratio) to the given sizes */ + + ret = g_new(ObClientIcon, 1); + ret->data = data; + ret->width = w; + ret->height = h; + return ret; +} + +void clienticon_free(ObClientIcon *ci) +{ + if (ci) { + g_free(ci->data); + g_free(ci); + } +}