X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fframe.c;h=fef8b833dae752aa73b8081bf28187f94e8ef57e;hb=0f677834e253dfd18a246c8811bf4a4e364d5e0e;hp=e5b4cdebbb568249a5010a05d90c478f14cd7e0e;hpb=547da2733235d9517e9ea2bdca7c3e38fe719c4f;p=chaz%2Fopenbox diff --git a/openbox/frame.c b/openbox/frame.c index e5b4cdeb..fef8b833 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -31,22 +31,17 @@ #include "screen.h" #include "render/theme.h" -#define PLATE_EVENTMASK (SubstructureRedirectMask | FocusChangeMask) #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \ - ButtonPressMask | ButtonReleaseMask) + ButtonPressMask | ButtonReleaseMask | \ + SubstructureRedirectMask | FocusChangeMask) #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \ ButtonMotionMask | PointerMotionMask | \ EnterWindowMask | LeaveWindowMask) -/* The inner window does not need enter/leave events. - If it does get them, then it needs its own context for enter events - because sloppy focus will focus the window when you enter the inner window - from the frame. */ -#define INNER_EVENTMASK (ButtonPressMask) #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */ #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */ -#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_y) +#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b) static void flash_done(gpointer data); static gboolean flash_timeout(gpointer data); @@ -100,7 +95,7 @@ ObFrame *frame_new(ObClient *client) /* create the non-visible decor windows */ - mask = CWEventMask; + mask = 0; if (visual) { /* client has a 32-bit visual */ mask |= CWColormap | CWBackPixel | CWBorderPixel; @@ -112,24 +107,22 @@ ObFrame *frame_new(ObClient *client) attrib.background_pixel = BlackPixel(ob_display, ob_screen); attrib.border_pixel = BlackPixel(ob_display, ob_screen); } - attrib.event_mask = FRAME_EVENTMASK; self->window = createWindow(RootWindow(ob_display, ob_screen), visual, mask, &attrib); - attrib.event_mask = INNER_EVENTMASK; - self->inner = createWindow(self->window, visual, mask, &attrib); - - mask &= ~CWEventMask; - self->plate = createWindow(self->inner, visual, mask, &attrib); - /* create the visible decor windows */ - mask = CWEventMask; + mask = 0; if (visual) { /* client has a 32-bit visual */ mask |= CWColormap | CWBackPixel | CWBorderPixel; attrib.colormap = RrColormap(ob_rr_inst); } + + self->backback = createWindow(self->window, NULL, mask, &attrib); + self->backfront = createWindow(self->backback, NULL, mask, &attrib); + + mask |= CWEventMask; attrib.event_mask = ELEMENT_EVENTMASK; self->title = createWindow(self->window, NULL, mask, &attrib); self->titleleft = createWindow(self->window, NULL, mask, &attrib); @@ -148,6 +141,11 @@ ObFrame *frame_new(ObClient *client) self->left = createWindow(self->window, NULL, mask, &attrib); self->right = createWindow(self->window, NULL, mask, &attrib); + self->innerleft = createWindow(self->window, NULL, mask, &attrib); + self->innertop = createWindow(self->window, NULL, mask, &attrib); + self->innerright = createWindow(self->window, NULL, mask, &attrib); + self->innerbottom = createWindow(self->window, NULL, mask, &attrib); + self->label = createWindow(self->title, NULL, mask, &attrib); self->max = createWindow(self->title, NULL, mask, &attrib); self->close = createWindow(self->title, NULL, mask, &attrib); @@ -175,9 +173,9 @@ ObFrame *frame_new(ObClient *client) self->focused = FALSE; /* the other stuff is shown based on decor settings */ - XMapWindow(ob_display, self->plate); - XMapWindow(ob_display, self->inner); XMapWindow(ob_display, self->label); + XMapWindow(ob_display, self->backback); + XMapWindow(ob_display, self->backfront); self->max_press = self->close_press = self->desk_press = self->iconify_press = self->shade_press = FALSE; @@ -340,18 +338,22 @@ void frame_adjust_area(ObFrame *self, gboolean moved, if (self->decorations & OB_FRAME_DECOR_BORDER) { self->bwidth = ob_rr_theme->fbwidth; - self->cbwidth_x = ob_rr_theme->cbwidthx; - self->cbwidth_y = ob_rr_theme->cbwidthy; + self->cbwidth_l = self->cbwidth_r = ob_rr_theme->cbwidthx; + self->cbwidth_t = self->cbwidth_b = ob_rr_theme->cbwidthy; } else { - self->bwidth = self->cbwidth_x = self->cbwidth_y = 0; + self->bwidth = self->cbwidth_l = self->cbwidth_t = + self->cbwidth_r = self->cbwidth_b = 0; } self->rbwidth = self->bwidth; if (self->max_horz) { - self->cbwidth_x = 0; + self->cbwidth_l = self->cbwidth_r = 0; self->width = self->client->area.width - self->bwidth * 2; + if (self->max_vert) + self->cbwidth_b = 0; } else - self->width = self->client->area.width + self->cbwidth_x * 2; + self->width = self->client->area.width + + self->cbwidth_l + self->cbwidth_r; /* some elements are sized based of the width, so don't let them have negative values */ @@ -359,10 +361,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved, (ob_rr_theme->grip_width + self->bwidth) * 2 + 1); STRUT_SET(self->size, - self->cbwidth_x + (!self->max_horz ? self->bwidth : 0), - self->cbwidth_y + self->bwidth, - self->cbwidth_x + (!self->max_horz ? self->bwidth : 0), - self->cbwidth_y + self->bwidth); + self->cbwidth_l + (!self->max_horz ? self->bwidth : 0), + self->cbwidth_t + self->bwidth, + self->cbwidth_r + (!self->max_horz ? self->bwidth : 0), + self->cbwidth_b + (!self->max_horz || !self->max_vert ? self->bwidth : 0)); if (self->decorations & OB_FRAME_DECOR_TITLEBAR) self->size.top += ob_rr_theme->title_height + self->rbwidth; @@ -375,6 +377,50 @@ void frame_adjust_area(ObFrame *self, gboolean moved, /* position/size and map/unmap all the windows */ if (!fake) { + if (self->cbwidth_l) { + XMoveResizeWindow(ob_display, self->innerleft, + self->size.left - self->cbwidth_l, + self->size.top, + self->cbwidth_l, self->client->area.height); + + XMapWindow(ob_display, self->innerleft); + } else + XUnmapWindow(ob_display, self->innerleft); + + if (self->cbwidth_r) { + XMoveResizeWindow(ob_display, self->innerright, + self->size.left + self->client->area.width, + self->size.top, + self->cbwidth_r, self->client->area.height); + + XMapWindow(ob_display, self->innerright); + } else + XUnmapWindow(ob_display, self->innerright); + + if (self->cbwidth_t) { + XMoveResizeWindow(ob_display, self->innertop, + self->size.left - self->cbwidth_l, + self->size.top - self->cbwidth_t, + self->client->area.width + + self->cbwidth_l + self->cbwidth_r, + self->cbwidth_t); + + XMapWindow(ob_display, self->innertop); + } else + XUnmapWindow(ob_display, self->innertop); + + if (self->cbwidth_b) { + XMoveResizeWindow(ob_display, self->innerbottom, + self->size.left - self->cbwidth_l, + self->size.top + self->client->area.height, + self->client->area.width + + self->cbwidth_l + self->cbwidth_r, + self->cbwidth_b); + + XMapWindow(ob_display, self->innerbottom); + } else + XUnmapWindow(ob_display, self->innerbottom); + if (self->bwidth) { gint titlesides; @@ -488,7 +534,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, layout_title(self); if (!fake) { - if (self->bwidth) { + if (self->bwidth && self->size.bottom) { XMoveResizeWindow(ob_display, self->handlebottom, ob_rr_theme->grip_width + self->bwidth * 2, @@ -504,11 +550,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->size.bottom - (!self->max_horz ? ob_rr_theme->grip_width : - self->size.bottom), + self->size.bottom - self->cbwidth_b), self->bwidth, (!self->max_horz ? ob_rr_theme->grip_width : - self->size.bottom)); + self->size.bottom - self->cbwidth_b)); XMoveResizeWindow(ob_display, self->rgripright, self->size.left + self->client->area.width + self->size.right - self->bwidth, @@ -516,11 +562,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->size.bottom - (!self->max_horz ? ob_rr_theme->grip_width : - self->size.bottom), + self->size.bottom - self->cbwidth_b), self->bwidth, (!self->max_horz ? ob_rr_theme->grip_width : - self->size.bottom)); + self->size.bottom - self->cbwidth_b)); XMoveResizeWindow(ob_display, self->lgripbottom, self->bwidth, @@ -667,7 +713,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, if (self->bwidth && !self->max_horz) { XMoveResizeWindow(ob_display, self->right, self->client->area.width + - self->cbwidth_x * 2 + self->bwidth, + self->cbwidth_l + self->cbwidth_r + self->bwidth, self->bwidth + ob_rr_theme->grip_width, self->bwidth, self->client->area.height + @@ -678,26 +724,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved, } else XUnmapWindow(ob_display, self->right); - /* move and resize the inner border window which contains the plate - */ - XMoveResizeWindow(ob_display, self->inner, - 0, - self->size.top - self->cbwidth_y, - self->client->area.width + - self->cbwidth_x * 2 + - (!self->max_horz ? self->bwidth * 2 : 0), - self->client->area.height + - self->cbwidth_y * 2); - - /* move the plate */ - XMoveWindow(ob_display, self->plate, - (!self->max_horz ? self->bwidth : 0) + self->cbwidth_x, - self->cbwidth_y); - - /* when the client has StaticGravity, it likes to move around. */ - XMoveWindow(ob_display, self->client->window, - -self->client->border_width, - -self->client->border_width); + XMoveResizeWindow(ob_display, self->backback, + self->size.left, self->size.top, + self->client->area.width, + self->client->area.height); } } @@ -734,6 +764,13 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->area.width, self->area.height); + /* when the client has StaticGravity, it likes to move around. + also this correctly positions the client when it maps. + this also needs to be run when the frame's decorations sizes change! + */ + XMoveWindow(ob_display, self->client->window, + self->size.left, self->size.top); + if (resized) { framerender_frame(self); frame_adjust_shape(self); @@ -782,6 +819,7 @@ static void frame_adjust_cursors(ObFrame *self) XChangeWindowAttributes(ob_display, self->handle, CWCursor, &a); XChangeWindowAttributes(ob_display, self->handletop, CWCursor, &a); XChangeWindowAttributes(ob_display, self->handlebottom, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerbottom, CWCursor, &a); /* these ones don't */ a.cursor = ob_cursor(r ? OB_CURSOR_NORTHWEST : OB_CURSOR_NONE); @@ -796,8 +834,10 @@ static void frame_adjust_cursors(ObFrame *self) XChangeWindowAttributes(ob_display, self->titleright, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->left, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerleft, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->right, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerright, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->lgrip, CWCursor, &a); XChangeWindowAttributes(ob_display, self->handleleft, CWCursor, &a); @@ -815,9 +855,10 @@ static void frame_adjust_cursors(ObFrame *self) void frame_adjust_client_area(ObFrame *self) { - /* resize the plate */ - XResizeWindow(ob_display, self->plate, - self->client->area.width, self->client->area.height); + /* adjust the window which is there to prevent flashing on unmap */ + XMoveResizeWindow(ob_display, self->backfront, 0, 0, + self->client->area.width, + self->client->area.height); } void frame_adjust_state(ObFrame *self) @@ -850,8 +891,7 @@ void frame_grab_client(ObFrame *self) */ /* reparent the client to the frame */ - XReparentWindow(ob_display, self->client->window, self->plate, - -self->client->border_width, -self->client->border_width); + XReparentWindow(ob_display, self->client->window, self->window, 0, 0); /* When reparenting the client window, it is usually not mapped yet, since @@ -864,12 +904,16 @@ void frame_grab_client(ObFrame *self) /* select the event mask on the client's parent (to receive config/map req's) the ButtonPress is to catch clicks on the client border */ - XSelectInput(ob_display, self->plate, PLATE_EVENTMASK); + XSelectInput(ob_display, self->window, FRAME_EVENTMASK); /* set all the windows for the frame in the window_map */ g_hash_table_insert(window_map, &self->window, self->client); - g_hash_table_insert(window_map, &self->plate, self->client); - g_hash_table_insert(window_map, &self->inner, self->client); + g_hash_table_insert(window_map, &self->backback, self->client); + g_hash_table_insert(window_map, &self->backfront, self->client); + g_hash_table_insert(window_map, &self->innerleft, self->client); + g_hash_table_insert(window_map, &self->innertop, self->client); + g_hash_table_insert(window_map, &self->innerright, self->client); + g_hash_table_insert(window_map, &self->innerbottom, self->client); g_hash_table_insert(window_map, &self->title, self->client); g_hash_table_insert(window_map, &self->label, self->client); g_hash_table_insert(window_map, &self->max, self->client); @@ -926,7 +970,7 @@ void frame_release_client(ObFrame *self) Reparent events that are generated by us are just discarded here. They are of no consequence to us anyhow. */ - if (ev.xreparent.parent != self->plate) { + if (ev.xreparent.parent != self->window) { reparent = FALSE; XPutBackEvent(ob_display, &ev); break; @@ -944,8 +988,12 @@ void frame_release_client(ObFrame *self) /* remove all the windows for the frame from the window_map */ g_hash_table_remove(window_map, &self->window); - g_hash_table_remove(window_map, &self->plate); - g_hash_table_remove(window_map, &self->inner); + g_hash_table_remove(window_map, &self->backback); + g_hash_table_remove(window_map, &self->backfront); + g_hash_table_remove(window_map, &self->innerleft); + g_hash_table_remove(window_map, &self->innertop); + g_hash_table_remove(window_map, &self->innerright); + g_hash_table_remove(window_map, &self->innerbottom); g_hash_table_remove(window_map, &self->title); g_hash_table_remove(window_map, &self->label); g_hash_table_remove(window_map, &self->max); @@ -1014,7 +1062,7 @@ static void layout_title(ObFrame *self) /* position of the left most button */ const gint left = ob_rr_theme->paddingx + 1; /* position of the right most button */ - const gint right = self->width - bwidth; + const gint right = self->width; /* turn them all off */ self->icon_on = self->desk_on = self->shade_on = self->iconify_on = @@ -1055,43 +1103,49 @@ static void layout_title(ObFrame *self) if ((self->icon_on = is_button_present(self, lc, i))) { /* icon is bigger than buttons */ self->label_width -= bwidth + 2; - self->icon_x = x; + if (i > 0) self->icon_x = x; x += i * (bwidth + 2); + if (i < 0) self->icon_x = x; } } else if (*lc == 'D') { if (firstcon) *firstcon = OB_FRAME_CONTEXT_ALLDESKTOPS; if ((self->desk_on = is_button_present(self, lc, i))) { self->label_width -= bwidth; - self->desk_x = x; + if (i > 0) self->desk_x = x; x += i * bwidth; + if (i < 0) self->desk_x = x; } } else if (*lc == 'S') { if (firstcon) *firstcon = OB_FRAME_CONTEXT_SHADE; if ((self->shade_on = is_button_present(self, lc, i))) { self->label_width -= bwidth; - self->shade_x = x; + if (i > 0) self->shade_x = x; x += i * bwidth; + if (i < 0) self->shade_x = x; } } else if (*lc == 'I') { if (firstcon) *firstcon = OB_FRAME_CONTEXT_ICONIFY; if ((self->iconify_on = is_button_present(self, lc, i))) { self->label_width -= bwidth; - self->iconify_x = x; + if (i > 0) self->iconify_x = x; x += i * bwidth; + if (i < 0) self->iconify_x = x; } } else if (*lc == 'M') { if (firstcon) *firstcon = OB_FRAME_CONTEXT_MAXIMIZE; if ((self->max_on = is_button_present(self, lc, i))) { self->label_width -= bwidth; - self->max_x = x; + if (i > 0) self->max_x = x; x += i * bwidth; + if (i < 0) self->max_x = x; } } else if (*lc == 'C') { if (firstcon) *firstcon = OB_FRAME_CONTEXT_CLOSE; if ((self->close_on = is_button_present(self, lc, i))) { self->label_width -= bwidth; - self->close_x = x; + if (i > 0) self->close_x = x; x += i * bwidth; + if (i < 0) self->close_x = x; } } else continue; /* don't set firstcon */ @@ -1215,13 +1269,6 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y) } self = client->frame; - if (win == self->inner || win == self->plate) { - /* conceptually, this is the desktop, as far as users are - concerned */ - if (client->type == OB_CLIENT_TYPE_DESKTOP) - return OB_FRAME_CONTEXT_DESKTOP; - return OB_FRAME_CONTEXT_CLIENT; - } /* when the user clicks in the corners of the titlebar and the client is fully maximized, then treat it like they clicked in the @@ -1298,6 +1345,7 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y) if (win == self->rgriptop) return OB_FRAME_CONTEXT_BLCORNER; if (win == self->rgripbottom) return OB_FRAME_CONTEXT_BLCORNER; if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR; + if (win == self->titlebottom) return OB_FRAME_CONTEXT_TITLEBAR; if (win == self->titleleft) return OB_FRAME_CONTEXT_TLCORNER; if (win == self->titletopleft) return OB_FRAME_CONTEXT_TLCORNER; if (win == self->titleright) return OB_FRAME_CONTEXT_TRCORNER; @@ -1310,6 +1358,10 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y) if (win == self->trrresize) return OB_FRAME_CONTEXT_TRCORNER; if (win == self->left) return OB_FRAME_CONTEXT_LEFT; if (win == self->right) return OB_FRAME_CONTEXT_RIGHT; + if (win == self->innertop) return OB_FRAME_CONTEXT_TITLEBAR; + if (win == self->innerleft) return OB_FRAME_CONTEXT_LEFT; + if (win == self->innerbottom) return OB_FRAME_CONTEXT_BOTTOM; + if (win == self->innerright) return OB_FRAME_CONTEXT_RIGHT; if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE; if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY; if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;