diff --git a/uspace/app/taskbar/wndlist.c b/uspace/app/taskbar/wndlist.c index 178901c932..c23adb7e34 100644 --- a/uspace/app/taskbar/wndlist.c +++ b/uspace/app/taskbar/wndlist.c @@ -716,13 +716,27 @@ errno_t wndlist_repaint(wndlist_t *wndlist) static void wndlist_button_clicked(ui_pbutton_t *pbutton, void *arg) { wndlist_entry_t *entry = (wndlist_entry_t *)arg; + wndmgt_window_info_t *winfo = NULL; sysarg_t dev_id; + errno_t rc; + bool minimized = false; /* ID of device that clicked the button */ dev_id = entry->wndlist->ev_idev_id; - (void) wndmgt_activate_window(entry->wndlist->wndmgt, - dev_id, entry->wnd_id); + rc = wndmgt_get_window_info(entry->wndlist->wndmgt, + entry->wnd_id, &winfo); + if (rc == EOK) { + minimized = (winfo->flags & wndf_minimized) == 0; + } + + if (!minimized) { + (void) wndmgt_activate_window(entry->wndlist->wndmgt, + dev_id, entry->wnd_id); + } else { + (void) wndmgt_deactivate_window(entry->wndlist->wndmgt, + dev_id, entry->wnd_id); + } } /** @} diff --git a/uspace/lib/wndmgt/include/ipc/wndmgt.h b/uspace/lib/wndmgt/include/ipc/wndmgt.h index bd0e815cdc..276641eef7 100644 --- a/uspace/lib/wndmgt/include/ipc/wndmgt.h +++ b/uspace/lib/wndmgt/include/ipc/wndmgt.h @@ -42,6 +42,7 @@ typedef enum { WNDMGT_GET_WINDOW_LIST, WNDMGT_GET_WINDOW_INFO, WNDMGT_ACTIVATE_WINDOW, + WNDMGT_DEACTIVATE_WINDOW, WNDMGT_CLOSE_WINDOW, WNDMGT_GET_EVENT, } wndmgt_request_t; diff --git a/uspace/lib/wndmgt/include/wndmgt.h b/uspace/lib/wndmgt/include/wndmgt.h index 511969d5df..ef22dfc854 100644 --- a/uspace/lib/wndmgt/include/wndmgt.h +++ b/uspace/lib/wndmgt/include/wndmgt.h @@ -47,6 +47,7 @@ extern errno_t wndmgt_get_window_info(wndmgt_t *, sysarg_t, wndmgt_window_info_t **); extern void wndmgt_free_window_info(wndmgt_window_info_t *); extern errno_t wndmgt_activate_window(wndmgt_t *, sysarg_t, sysarg_t); +extern errno_t wndmgt_deactivate_window(wndmgt_t *, sysarg_t, sysarg_t); extern errno_t wndmgt_close_window(wndmgt_t *, sysarg_t); #endif diff --git a/uspace/lib/wndmgt/include/wndmgt_srv.h b/uspace/lib/wndmgt/include/wndmgt_srv.h index 7603611edc..aa549a8a2c 100644 --- a/uspace/lib/wndmgt/include/wndmgt_srv.h +++ b/uspace/lib/wndmgt/include/wndmgt_srv.h @@ -52,6 +52,7 @@ struct wndmgt_ops { errno_t (*get_window_list)(void *, wndmgt_window_list_t **); errno_t (*get_window_info)(void *, sysarg_t, wndmgt_window_info_t **); errno_t (*activate_window)(void *, sysarg_t, sysarg_t); + errno_t (*deactivate_window)(void *, sysarg_t, sysarg_t); errno_t (*close_window)(void *, sysarg_t); errno_t (*get_event)(void *, wndmgt_ev_t *); }; diff --git a/uspace/lib/wndmgt/src/wndmgt.c b/uspace/lib/wndmgt/src/wndmgt.c index e3c2316e34..9e8e6a94d3 100644 --- a/uspace/lib/wndmgt/src/wndmgt.c +++ b/uspace/lib/wndmgt/src/wndmgt.c @@ -307,6 +307,28 @@ errno_t wndmgt_activate_window(wndmgt_t *wndmgt, sysarg_t dev_id, return rc; } +/** Deactivate (minimize) window. + * + * @param wndmgt Window management session + * @param dev_id ID of input device belonging to seat whose + * focus is to be switched + * @param wnd_id Window ID + * @return EOK on success or an error code + */ +errno_t wndmgt_deactivate_window(wndmgt_t *wndmgt, sysarg_t dev_id, + sysarg_t wnd_id) +{ + async_exch_t *exch; + errno_t rc; + + exch = async_exchange_begin(wndmgt->sess); + rc = async_req_2_0(exch, WNDMGT_DEACTIVATE_WINDOW, dev_id, + wnd_id); + + async_exchange_end(exch); + return rc; +} + /** Close window. * * @param wndmgt Window management diff --git a/uspace/lib/wndmgt/src/wndmgt_srv.c b/uspace/lib/wndmgt/src/wndmgt_srv.c index 492d33f3f0..32346acd8c 100644 --- a/uspace/lib/wndmgt/src/wndmgt_srv.c +++ b/uspace/lib/wndmgt/src/wndmgt_srv.c @@ -221,6 +221,24 @@ static void wndmgt_activate_window_srv(wndmgt_srv_t *srv, ipc_call_t *icall) async_answer_0(icall, rc); } +static void wndmgt_deactivate_window_srv(wndmgt_srv_t *srv, ipc_call_t *icall) +{ + sysarg_t dev_id; + sysarg_t wnd_id; + errno_t rc; + + dev_id = ipc_get_arg1(icall); + wnd_id = ipc_get_arg2(icall); + + if (srv->ops->deactivate_window == NULL) { + async_answer_0(icall, ENOTSUP); + return; + } + + rc = srv->ops->deactivate_window(srv->arg, dev_id, wnd_id); + async_answer_0(icall, rc); +} + static void wndmgt_close_window_srv(wndmgt_srv_t *srv, ipc_call_t *icall) { sysarg_t wnd_id; @@ -308,6 +326,9 @@ void wndmgt_conn(ipc_call_t *icall, wndmgt_srv_t *srv) case WNDMGT_ACTIVATE_WINDOW: wndmgt_activate_window_srv(srv, &call); break; + case WNDMGT_DEACTIVATE_WINDOW: + wndmgt_deactivate_window_srv(srv, &call); + break; case WNDMGT_CLOSE_WINDOW: wndmgt_close_window_srv(srv, &call); break; diff --git a/uspace/srv/hid/display/wmops.c b/uspace/srv/hid/display/wmops.c index 769ca77acd..bd390be637 100644 --- a/uspace/srv/hid/display/wmops.c +++ b/uspace/srv/hid/display/wmops.c @@ -46,6 +46,7 @@ static errno_t dispwm_get_window_list(void *, wndmgt_window_list_t **); static errno_t dispwm_get_window_info(void *, sysarg_t, wndmgt_window_info_t **); static errno_t dispwm_activate_window(void *, sysarg_t, sysarg_t); +static errno_t dispwm_deactivate_window(void *, sysarg_t, sysarg_t); static errno_t dispwm_close_window(void *, sysarg_t); static errno_t dispwm_get_event(void *, wndmgt_ev_t *); @@ -53,6 +54,7 @@ wndmgt_ops_t wndmgt_srv_ops = { .get_window_list = dispwm_get_window_list, .get_window_info = dispwm_get_window_info, .activate_window = dispwm_activate_window, + .deactivate_window = dispwm_deactivate_window, .close_window = dispwm_close_window, .get_event = dispwm_get_event, }; @@ -188,6 +190,34 @@ static errno_t dispwm_activate_window(void *arg, sysarg_t dev_id, return EOK; } +/** Deactivate (minimize) window. + * + * @param arg Argument (WM client) + * @param dev_id Input device ID + * @param wnd_id Window ID + * @return EOK on success or an error code + */ +static errno_t dispwm_deactivate_window(void *arg, sysarg_t dev_id, + sysarg_t wnd_id) +{ + ds_wmclient_t *wmclient = (ds_wmclient_t *)arg; + ds_window_t *wnd; + + log_msg(LOG_DEFAULT, LVL_DEBUG, "dispwm_deactivate_window()"); + + ds_display_lock(wmclient->display); + wnd = ds_display_find_window(wmclient->display, wnd_id); + if (wnd == NULL) { + ds_display_unlock(wmclient->display); + return ENOENT; + } + + ds_window_minimize(wnd); + + ds_display_unlock(wmclient->display); + return EOK; +} + /** Close window. * * @param arg Argument (WM client)