1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 startupnotify.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003 Ben Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
20 #include "startupnotify.h"
24 void sn_startup(gboolean reconfig
) {}
25 void sn_shutdown(gboolean reconfig
) {}
26 gboolean
sn_app_starting() { return FALSE
; }
27 void sn_app_started(gchar
*wmclass
) {}
28 gboolean
sn_get_desktop(gchar
*id
, guint
*desktop
) { return FALSE
; }
36 #define SN_API_NOT_YET_FROZEN
40 SnStartupSequence
*seq
;
44 static SnDisplay
*sn_display
;
45 static SnMonitorContext
*sn_context
;
46 static GSList
*sn_waits
; /* list of ObWaitDatas */
48 static ObWaitData
* wait_data_new(SnStartupSequence
*seq
);
49 static void wait_data_free(ObWaitData
*d
);
50 static ObWaitData
* wait_find(const gchar
*id
);
52 static void sn_handler(const XEvent
*e
, gpointer data
);
53 static void sn_event_func(SnMonitorEvent
*event
, gpointer data
);
55 void sn_startup(gboolean reconfig
)
59 sn_display
= sn_display_new(ob_display
, NULL
, NULL
);
60 sn_context
= sn_monitor_context_new(sn_display
, ob_screen
,
61 sn_event_func
, NULL
, NULL
);
63 ob_main_loop_x_add(ob_main_loop
, sn_handler
, NULL
, NULL
);
66 void sn_shutdown(gboolean reconfig
)
72 ob_main_loop_x_remove(ob_main_loop
, sn_handler
);
74 for (it
= sn_waits
; it
; it
= g_slist_next(it
))
75 wait_data_free(it
->data
);
76 g_slist_free(sn_waits
);
79 screen_set_root_cursor();
81 sn_monitor_context_unref(sn_context
);
82 sn_display_unref(sn_display
);
85 static ObWaitData
* wait_data_new(SnStartupSequence
*seq
)
87 ObWaitData
*d
= g_new(ObWaitData
, 1);
91 sn_startup_sequence_ref(d
->seq
);
96 static void wait_data_free(ObWaitData
*d
)
99 sn_startup_sequence_unref(d
->seq
);
105 static ObWaitData
* wait_find(const gchar
*id
)
107 ObWaitData
*ret
= NULL
;
110 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
111 ObWaitData
*d
= it
->data
;
112 if (!strcmp(id
, sn_startup_sequence_get_id(d
->seq
))) {
120 gboolean
sn_app_starting()
124 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
125 ObWaitData
*d
= it
->data
;
132 static gboolean
sn_wait_timeout(gpointer data
)
134 ObWaitData
*d
= data
;
136 screen_set_root_cursor();
137 return FALSE
; /* don't repeat */
140 static void sn_wait_destroy(gpointer data
)
142 ObWaitData
*d
= data
;
143 sn_waits
= g_slist_remove(sn_waits
, d
);
147 static void sn_handler(const XEvent
*e
, gpointer data
)
151 sn_display_process_event(sn_display
, &ec
);
154 static void sn_event_func(SnMonitorEvent
*ev
, gpointer data
)
156 SnStartupSequence
*seq
;
157 gboolean change
= FALSE
;
160 if (!(seq
= sn_monitor_event_get_startup_sequence(ev
)))
163 switch (sn_monitor_event_get_type(ev
)) {
164 case SN_MONITOR_EVENT_INITIATED
:
165 d
= wait_data_new(seq
);
166 sn_waits
= g_slist_prepend(sn_waits
, d
);
167 /* 30 second timeout for apps to start */
168 ob_main_loop_timeout_add(ob_main_loop
, 30 * G_USEC_PER_SEC
,
169 sn_wait_timeout
, d
, sn_wait_destroy
);
172 case SN_MONITOR_EVENT_CHANGED
:
173 /* XXX feedback changed? */
176 case SN_MONITOR_EVENT_COMPLETED
:
177 case SN_MONITOR_EVENT_CANCELED
:
178 if ((d
= wait_find(sn_startup_sequence_get_id(seq
)))) {
180 ob_main_loop_timeout_remove_data(ob_main_loop
, sn_wait_timeout
,
188 screen_set_root_cursor();
191 void sn_app_started(gchar
*wmclass
)
195 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
196 ObWaitData
*d
= it
->data
;
197 if (sn_startup_sequence_get_wmclass(d
->seq
) &&
198 !strcmp(sn_startup_sequence_get_wmclass(d
->seq
), wmclass
))
200 sn_startup_sequence_complete(d
->seq
);
206 gboolean
sn_get_desktop(gchar
*id
, guint
*desktop
)
210 if (id
&& (d
= wait_find(id
))) {
211 gint desk
= sn_startup_sequence_get_workspace(d
->seq
);