aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Zandr Martin <zandrmartin@gmail.com>2016-10-02 22:03:52 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2016-10-04 17:25:10 -0400
commit33fe87a1fb893b06a69ad82f12db6a869a8f2681 (patch)
treeb6200de156759d6696163c35bf18c8d53c762e2b
parentconsolidate nodes json (diff)
downloadsway-33fe87a1fb893b06a69ad82f12db6a869a8f2681.tar.gz
sway-33fe87a1fb893b06a69ad82f12db6a869a8f2681.tar.zst
sway-33fe87a1fb893b06a69ad82f12db6a869a8f2681.zip
prevent dereference of freed workspace0.10-rc2
-rw-r--r--sway/focus.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/sway/focus.c b/sway/focus.c
index 35dff1e4..e9b032f8 100644
--- a/sway/focus.c
+++ b/sway/focus.c
@@ -1,3 +1,4 @@
1#include "stdbool.h"
1#include <wlc/wlc.h> 2#include <wlc/wlc.h>
2#include "sway/focus.h" 3#include "sway/focus.h"
3#include "sway/workspace.h" 4#include "sway/workspace.h"
@@ -99,14 +100,24 @@ bool set_focused_container(swayc_t *c) {
99 if (locked_container_focus || !c || !c->parent) { 100 if (locked_container_focus || !c || !c->parent) {
100 return false; 101 return false;
101 } 102 }
102 swayc_t *active_ws = swayc_active_workspace(); 103
103 int active_ws_child_count = 0; 104 // current ("old") workspace for sending workspace change event later
104 if (active_ws) { 105 swayc_t *old_ws = swayc_active_workspace();
105 active_ws_child_count = active_ws->children->length + active_ws->floating->length; 106 // keep track of child count so we can determine if it gets destroyed
107 int old_ws_child_count = 0;
108 if (old_ws) {
109 old_ws_child_count = old_ws->children->length + old_ws->floating->length;
106 } 110 }
107 111
112 // current ("old") focused container
113 swayc_t *old_focus = get_focused_container(&root_container);
114 // if old_focus is a workspace, then it's the same workspace as
115 // old_ws, and we'll need to null its pointer too, since it will
116 // be destroyed in the update_focus() call
117 bool old_focus_was_ws = (old_focus->type == C_WORKSPACE);
118
119 // workspace of new focused container
108 swayc_t *workspace = swayc_active_workspace_for(c); 120 swayc_t *workspace = swayc_active_workspace_for(c);
109 swayc_t *focused = get_focused_container(&root_container);
110 121
111 if (swayc_is_fullscreen(get_focused_container(workspace))) { 122 if (swayc_is_fullscreen(get_focused_container(workspace))) {
112 // if switching to a workspace with a fullscreen view, 123 // if switching to a workspace with a fullscreen view,
@@ -136,11 +147,19 @@ bool set_focused_container(swayc_t *c) {
136 p->is_focused = false; 147 p->is_focused = false;
137 } 148 }
138 149
150 if (old_focus_was_ws && old_ws_child_count == 0) {
151 // this workspace was destroyed in update_focus(), so null the pointers
152 old_focus = NULL;
153 old_ws = NULL;
154 }
155
139 if (!(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { 156 if (!(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) {
140 if (focused->type == C_VIEW) { 157 if (old_focus) {
141 wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); 158 if (old_focus->type == C_VIEW) {
159 wlc_view_set_state(old_focus->handle, WLC_BIT_ACTIVATED, false);
160 }
161 update_container_border(old_focus);
142 } 162 }
143 update_container_border(focused);
144 if (c->type == C_VIEW) { 163 if (c->type == C_VIEW) {
145 wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); 164 wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true);
146 } 165 }
@@ -161,15 +180,11 @@ bool set_focused_container(swayc_t *c) {
161 } 180 }
162 } 181 }
163 182
164 if (active_ws != workspace) { 183 if (old_ws != workspace) {
165 // active_ws might have been destroyed by now 184 // old_ws might be NULL here but that's ok
166 // (focus swap away from empty ws = destroy ws) 185 ipc_event_workspace(old_ws, workspace, "focus");
167 if (active_ws_child_count == 0) {
168 active_ws = NULL;
169 }
170
171 ipc_event_workspace(active_ws, workspace, "focus");
172 } 186 }
187
173 return true; 188 return true;
174} 189}
175 190