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 Time
sn_app_started(const gchar
*id
, const gchar
*wmclass
)
31 gboolean
sn_get_desktop(gchar
*id
, guint
*desktop
) { return FALSE
; }
39 #define SN_API_NOT_YET_FROZEN
43 SnStartupSequence
*seq
;
47 static SnDisplay
*sn_display
;
48 static SnMonitorContext
*sn_context
;
49 static GSList
*sn_waits
; /* list of ObWaitDatas */
51 static ObWaitData
* wait_data_new(SnStartupSequence
*seq
);
52 static void wait_data_free(ObWaitData
*d
);
53 static ObWaitData
* wait_find(const gchar
*id
);
55 static void sn_handler(const XEvent
*e
, gpointer data
);
56 static void sn_event_func(SnMonitorEvent
*event
, gpointer data
);
58 void sn_startup(gboolean reconfig
)
62 sn_display
= sn_display_new(ob_display
, NULL
, NULL
);
63 sn_context
= sn_monitor_context_new(sn_display
, ob_screen
,
64 sn_event_func
, NULL
, NULL
);
66 ob_main_loop_x_add(ob_main_loop
, sn_handler
, NULL
, NULL
);
69 void sn_shutdown(gboolean reconfig
)
75 ob_main_loop_x_remove(ob_main_loop
, sn_handler
);
77 for (it
= sn_waits
; it
; it
= g_slist_next(it
))
78 wait_data_free(it
->data
);
79 g_slist_free(sn_waits
);
82 screen_set_root_cursor();
84 sn_monitor_context_unref(sn_context
);
85 sn_display_unref(sn_display
);
88 static ObWaitData
* wait_data_new(SnStartupSequence
*seq
)
90 ObWaitData
*d
= g_new(ObWaitData
, 1);
94 sn_startup_sequence_ref(d
->seq
);
99 static void wait_data_free(ObWaitData
*d
)
102 sn_startup_sequence_unref(d
->seq
);
108 static ObWaitData
* wait_find(const gchar
*id
)
110 ObWaitData
*ret
= NULL
;
113 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
114 ObWaitData
*d
= it
->data
;
115 if (!strcmp(id
, sn_startup_sequence_get_id(d
->seq
))) {
123 gboolean
sn_app_starting()
127 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
128 ObWaitData
*d
= it
->data
;
135 static gboolean
sn_wait_timeout(gpointer data
)
137 ObWaitData
*d
= data
;
139 screen_set_root_cursor();
140 return FALSE
; /* don't repeat */
143 static void sn_wait_destroy(gpointer data
)
145 ObWaitData
*d
= data
;
146 sn_waits
= g_slist_remove(sn_waits
, d
);
150 static void sn_handler(const XEvent
*e
, gpointer data
)
154 sn_display_process_event(sn_display
, &ec
);
157 static void sn_event_func(SnMonitorEvent
*ev
, gpointer data
)
159 SnStartupSequence
*seq
;
160 gboolean change
= FALSE
;
163 if (!(seq
= sn_monitor_event_get_startup_sequence(ev
)))
166 switch (sn_monitor_event_get_type(ev
)) {
167 case SN_MONITOR_EVENT_INITIATED
:
168 d
= wait_data_new(seq
);
169 sn_waits
= g_slist_prepend(sn_waits
, d
);
170 /* 15 second timeout for apps to start */
171 ob_main_loop_timeout_add(ob_main_loop
, 15 * G_USEC_PER_SEC
,
172 sn_wait_timeout
, d
, sn_wait_destroy
);
175 case SN_MONITOR_EVENT_CHANGED
:
176 /* XXX feedback changed? */
179 case SN_MONITOR_EVENT_COMPLETED
:
180 case SN_MONITOR_EVENT_CANCELED
:
181 if ((d
= wait_find(sn_startup_sequence_get_id(seq
)))) {
183 ob_main_loop_timeout_remove_data(ob_main_loop
, sn_wait_timeout
,
191 screen_set_root_cursor();
194 Time
sn_app_started(const gchar
*id
, const gchar
*wmclass
)
197 Time t
= CurrentTime
;
199 for (it
= sn_waits
; it
; it
= g_slist_next(it
)) {
200 ObWaitData
*d
= it
->data
;
201 const gchar
*seqid
, *seqclass
;
202 seqid
= sn_startup_sequence_get_id(d
->seq
);
203 seqclass
= sn_startup_sequence_get_wmclass(d
->seq
);
204 if ((seqid
&& id
&& !strcmp(seqid
, id
)) ||
205 (seqclass
&& wmclass
&& !strcmp(seqclass
, wmclass
)))
207 sn_startup_sequence_complete(d
->seq
);
208 t
= sn_startup_sequence_get_timestamp(d
->seq
);
215 gboolean
sn_get_desktop(gchar
*id
, guint
*desktop
)
219 if (id
&& (d
= wait_find(id
))) {
220 gint desk
= sn_startup_sequence_get_workspace(d
->seq
);