4 X11 resolution selector (for Window Maker)
5 by Sébastien "Slix" Liénard <slix@gcu-squad.org>, GCU Squad (http://gcu-squad.org)
6 based on gvidm and wmtimer
7 and licensed through the GNU General Public License.
9 Read the COPYING file for the complete GNU license.
20 #include <sys/utsname.h>
24 #include <X11/extensions/shape.h>
25 #include <X11/extensions/xf86vmode.h>
27 #define V_PHSYNC 0x001
28 #define V_NHSYNC 0x002
29 #define V_PVSYNC 0x004
30 #define V_NVSYNC 0x008
31 #define V_INTERLACE 0x010
32 #define V_DBLSCAN 0x020
34 #define V_PCSYNC 0x080
35 #define V_NCSYNC 0x100
37 #ifdef HAVE_LIBXINERAMA
38 #include <X11/extensions/Xinerama.h>
43 #include <libdockapp/wmgeneral.h>
44 #include <libdockapp/misc.h>
46 #include "wmressel-master.xpm"
47 #include "wmressel-mask.xbm"
49 #define MY_EMAIL "slix@gcu-squad.org"
50 #define GCU_HOME "http://gcu-squad.org/"
58 void printVersion(void);
59 void BlitString(char *name
, int x
, int y
);
60 void BlitNum(int num
, int x
, int y
);
61 void wmressel_routine(int, char **, int);
62 void MenuEvent (GtkWidget
*, gpointer
);
63 void on_deactivate(void);
64 void create_popup(int);
65 GtkWidget
*create_screen_submenu (int);
66 char *create_submenu_label(XF86VidModeModeInfo
*, XF86VidModeModeLine
, int);
67 void update_res_display(int);
68 void show_screen_number(int);
69 int get_screen_count(void);
72 int show_refresh_rate
=0;
73 int show_doublescan
=0;
74 int show_only_selected
=0;
76 int main(int argc
, char *argv
[])
79 int i
, selected_screen
=0;
82 /* Parse Command Line */
85 if (strlen(ProgName
) >= 5)
86 ProgName
+= (strlen(ProgName
) - 5);
88 for (i
=1; i
<argc
; i
++) {
94 /* wmgeneral.c has been modified to allow this trick: openXwindow and gtk_init */
95 /* use same option (--display) for display setting */
96 if (strcmp(arg
+1, "-display")) {
108 show_only_selected
=1;
115 selected_screen
= strtol(argv
[i
], &endp
, 10);
133 wmressel_routine(argc
, argv
, selected_screen
);
141 void wmressel_routine(int argc
, char **argv
, int selected_screen
)
146 int j
=0, show_number
=0, screen_count
;
148 openXwindow(argc
, argv
, wmressel_master_xpm
, wmressel_mask_bits
, wmressel_mask_width
, wmressel_mask_height
);
150 screen_count
= get_screen_count();
151 if (selected_screen
> screen_count
-1) {
152 printf("\nScreen number %i is not valid !!!\n", selected_screen
);
157 if (screen_count
> 1) {
158 show_screen_number(selected_screen
);
161 update_res_display(selected_screen
);
164 AddMouseRegion( 0, 5, 5, 55, 55);
166 gtk_init (&argc
, &argv
);
170 while (XPending(display
)) {
171 XNextEvent(display
, &Event
);
172 switch (Event
.type
) {
177 XCloseDisplay(display
);
181 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
185 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
186 if (but_stat
== i
&& but_stat
>= 0) {
188 screen_count
=get_screen_count();
190 if(Event
.xbutton
.button
==1) {
191 /* Left button pressed, popup menu */
192 create_popup(selected_screen
);
194 update_res_display(selected_screen
);
196 } else if (Event
.xbutton
.button
==3 && screen_count
>1) {
197 /* Right button pressed, view screen number */
198 show_screen_number(selected_screen
);
201 } else if (Event
.xbutton
.button
==4 && screen_count
>1) {
202 /* Mouse wheel up, select next screen */
203 if(selected_screen
==get_screen_count()-1) {
208 show_screen_number(selected_screen
);
211 } else if (Event
.xbutton
.button
==5 && screen_count
>1) {
212 /* Mouse wheel down, select previous screen */
213 if(selected_screen
==0) {
214 selected_screen
=get_screen_count()-1;
218 show_screen_number(selected_screen
);
229 update_res_display(selected_screen
);
238 /********************
239 * Create popup menu *
240 ********************/
241 void create_popup(int selected_screen
)
248 GtkWidget
*submenu_ptr
, *menuitem_ptr
;
249 int screen_count
= get_screen_count();
251 if (screen_count
> 1 && !show_only_selected
) {
252 menu_ptr
= gtk_menu_new();
253 for (i
=0; i
<screen_count
; i
++) {
254 submenu_ptr
= create_screen_submenu(0);
255 sprintf(label_str
, "Screen %i",i
);
256 menuitem_ptr
= gtk_menu_item_new_with_label(label_str
);
257 gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuitem_ptr
), submenu_ptr
);
258 gtk_menu_shell_append(GTK_MENU_SHELL (menu_ptr
), menuitem_ptr
);
259 gtk_widget_show(menuitem_ptr
);
260 gtk_widget_show(submenu_ptr
);
263 menu_ptr
= create_screen_submenu(selected_screen
);
266 g_signal_connect (G_OBJECT (menu_ptr
), "deactivate", G_CALLBACK (on_deactivate
), NULL
);
267 /* gtk_menu_popup() is deprecated, but we need a GdkWindow to
268 use any of its replacements, so keeping for now */
269 gtk_menu_popup(GTK_MENU(menu_ptr
), NULL
, NULL
, NULL
, NULL
, 0, 0);
272 /************************************************
273 * Procede GTK menu choice and switch resolution *
274 ************************************************/
275 void MenuEvent (GtkWidget
*widget
, gpointer menu_choice
) {
276 XF86VidModeModeInfo
**vm_modelines
;
279 XF86VidModeGetAllModeLines(display
, ((MENU_CHOICE
*)menu_choice
)->screen
, &vm_count
, &vm_modelines
);
280 XF86VidModeSwitchToMode(display
, ((MENU_CHOICE
*)menu_choice
)->screen
, vm_modelines
[((MENU_CHOICE
*)menu_choice
)->mode
]);
285 /***************************
286 * Return number of screens *
287 ***************************/
288 int get_screen_count()
291 #ifdef HAVE_LIBXINERAMA
293 int screen_exists
[1024];
294 XineramaScreenInfo
*screen
;
296 if (XineramaIsActive(display
)) {
297 screen
= XineramaQueryScreens(display
, screen_exists
);
298 for (i
=0; i
==screen
[i
].screen_number
; i
++){}
303 screen_count
= XScreenCount(display
);
304 #ifdef HAVE_LIBXINERAMA
307 return(screen_count
);
310 void on_deactivate(void) {
314 /*********************************
315 * Create a label for a menu item *
316 **********************************/
317 char *create_submenu_label(XF86VidModeModeInfo
*modeline
, XF86VidModeModeLine current
, int dotclock
)
320 char def
[3], res
[12];
324 label_str
= malloc(sizeof(def
)+sizeof(res
)+sizeof(rr
)+sizeof(ds
)-3);
326 if ((current
.hdisplay
==modeline
->hdisplay
) && (current
.vdisplay
==modeline
->vdisplay
) && (dotclock
==modeline
->dotclock
)) {
332 sprintf(res
, "%ix%i", modeline
->hdisplay
, modeline
->vdisplay
);
334 if (show_refresh_rate
) {
335 if ((modeline
->flags
) & V_DBLSCAN
) {
336 sprintf(rr
, "@%iHz", modeline
->dotclock
*500/(modeline
->htotal
*modeline
->vtotal
));
338 sprintf(rr
, "@%iHz", modeline
->dotclock
*1000/(modeline
->htotal
*modeline
->vtotal
));
342 if (show_doublescan
&& ((modeline
->flags
) & V_DBLSCAN
)) sprintf (ds
, " D");
344 sprintf(label_str
, "%s%s%s%s", def
, res
, rr
, ds
);
348 /*******************************************************
349 * Create menu composed of available modes for a screen *
350 *******************************************************/
351 GtkWidget
*create_screen_submenu (int screen
)
353 int i
, dotclock
, vm_count
=0;
354 MENU_CHOICE
*menu_choice
;
356 GtkWidget
*menuitem_ptr
, *menu_ptr
;
357 XF86VidModeModeInfo
**vm_modelines
;
358 XF86VidModeModeLine modeline
;
360 XF86VidModeGetAllModeLines(display
, screen
, &vm_count
, &vm_modelines
);
361 XF86VidModeGetModeLine(display
, screen
, &dotclock
, &modeline
);
363 menu_ptr
= gtk_menu_new();
365 for (i
=0; i
<vm_count
; i
++) {
367 label_str
= create_submenu_label(vm_modelines
[i
], modeline
, dotclock
);
369 menu_choice
= malloc(sizeof(menu_choice
));
370 menu_choice
->screen
=screen
;
373 menuitem_ptr
= gtk_menu_item_new_with_label(label_str
);
374 g_signal_connect(G_OBJECT (menuitem_ptr
), "activate", G_CALLBACK (MenuEvent
), (gpointer
)menu_choice
);
375 gtk_menu_shell_append(GTK_MENU_SHELL (menu_ptr
), menuitem_ptr
);
376 gtk_widget_show(menuitem_ptr
);
385 /******************************************
386 * Update displayed resolution information *
387 ******************************************/
388 void update_res_display(int screen
)
391 XF86VidModeModeLine modeline
;
392 XF86VidModeGetModeLine(display
, screen
, &dotclock
, &modeline
);
394 /* Clear screen zone */
395 copyXPMArea(76, 12, 35, 29, 14, 13);
397 /* Show resolution */
398 BlitNum(modeline
.hdisplay
, 41, 14);
399 BlitString("X", 15, 23);
400 BlitNum(modeline
.vdisplay
, 41, 23);
403 if ((modeline
.flags
) & V_DBLSCAN
) {
404 BlitNum(dotclock
*500/(modeline
.htotal
*modeline
.vtotal
), 29, 32);
406 BlitNum(dotclock
*1000/(modeline
.htotal
*modeline
.vtotal
), 29, 32);
408 BlitString("Hz", 35, 32);
413 /*****************************
414 * Show screen number (SCR X) *
415 *****************************/
416 void show_screen_number(int screen
)
418 /* Clear screen zone */
419 copyXPMArea(76, 12, 35, 29, 14, 13);
421 BlitString("Scr", 15, 23);
422 BlitNum(screen
, 41, 23);
426 /* Blits a string at given co-ordinates */
427 void BlitString(char *name
, int x
, int y
)
434 for (i
=0; name
[i
]; i
++) {
435 c
= toupper(name
[i
]);
436 if (c
>= 'A' && c
<= 'Z')
439 copyXPMArea(c
* 6, 74, 6, 8, k
, y
);
443 { /* its a number or symbol */
445 copyXPMArea(c
* 6, 64, 6, 8, k
, y
);
452 /* Blits number to give coordinates.. nine 0's, right justified */
454 void BlitNum(int num
, int x
, int y
)
459 if ( num
> 9 ) newx
-= 6;
460 if ( num
> 99 ) newx
-= 6;
461 if ( num
> 999 ) newx
-= 6;
462 if ( num
> 9999 ) newx
-= 6;
464 sprintf(buf
, "%i", num
);
466 BlitString(buf
, newx
, y
);
469 /*******************************************************************************\
471 \*******************************************************************************/
475 printf ("\n wmressel version %s -- X11 resolution selector for Window Maker\n", PACKAGE_VERSION
);
476 printf (" Copyright (C) 2002 Sébastien Liénard <%s>\n", MY_EMAIL
);
477 printf (" from GCU (%s)\n",GCU_HOME
);
478 printf (" This software comes with NO WARRANTY.\n\n");
480 printf ("\t-r\t\t\tShow refresh rates in menu\n");
481 printf ("\t-d\t\t\tShow in menu if a mode is a Doublescan mode (D)\n");
482 printf ("\t-s <number>\t\tShow information about this screen\n");
483 printf ("\t-o\t\t\tOnly show menu for selected screen\n");
484 printf ("\t--display <display>\tSet display\n");
485 printf ("\t-h\t\t\tthis help screen\n");
486 printf ("\t-v\t\t\tprint the version number\n");
490 /*******************************************************************************\
492 \*******************************************************************************/
494 void printVersion(void) {
495 fprintf(stderr
, "wmressel v%s\n", PACKAGE_VERSION
);